Search Unity

  1. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice
  2. Ever participated in one our Game Jams? Want pointers on your project? Our Evangelists will be available on Friday to give feedback. Come share your games with us!
    Dismiss Notice

Surface shaders not rendering as expected on Android (Oculus Quest)

Discussion in 'Shaders' started by KayH, Feb 23, 2020.

  1. KayH

    KayH

    Joined:
    Jan 6, 2017
    Posts:
    13
    Both shaders are surfaces shaders, Standard lighting, fullforwardshadows (disabled on Android though) and target 3.5. Both use instancing and texture arrays.

    I have two problems:

    One shader is overlit (too reflective/glossy).

    The other uses a perlin map for randomization. On Quest, it creates artifacts (looks like its lower res) and close up you can see that a part seems to be missing (texture not being sampled on either end of the perlin noise?).

    I fiddled with quality settings but none had any effect so I suppose it's a shader problem.

    Here are screenshots from the editor, showing how it's supposed to look:

    editor01.png
    The texture on the bricks is visible, not overlit.
    editor02.png
    The terrain doesn't have artifacts, no gaps.

    Here's how it looks on the device:

    quest01.jpg

    The texture on the brick is hardly visible, totally overlit.

    quest02.jpg
    There are gaps on one part of the perlin noise and there are visible seams.

    Any help would be appreciated, thanks.
     
    Last edited: Feb 24, 2020
  2. aleksandrk

    aleksandrk

    Unity Technologies

    Joined:
    Jul 3, 2017
    Posts:
    1,384
    Change
    fixed2 uv_MainTex;
    to
    float2 uv_MainTex;

    and do the same for the second UV set. This will help get rid of seams.

    For the textures, check quality settings.
     
  3. KayH

    KayH

    Joined:
    Jan 6, 2017
    Posts:
    13
    I changed fixed to float for the UVs, thanks. Will test later and check back if it helped with the seams.

    These are my current quality settings:
    quality.png
    I already tried different settings for the anisotropic textures (it was off originally). Other than that, I cycled through different presets, starting with medium going up to ultra. None of the settings I tried had any effect on the two problems I'm having.

    Also, the gaps on the terrain shader should be caused by the shader, shouldn't they? I mean it's the same texture that is sampled twice, only the second time offset and mirrored. But for some reason only one side of the lerp is showing the texture.
     
  4. aleksandrk

    aleksandrk

    Unity Technologies

    Joined:
    Jul 3, 2017
    Posts:
    1,384
    Check, which settings are used on Android, those are probably "Medium" by default.
    The look on the textures can be different due to different texture compression (it's ETC/ETC2 by default for Android).

    Gaps are likely a result of precision issues - desktop GPUs normally handle everything as full floats, but on mobile half is supported natively.
     
  5. KayH

    KayH

    Joined:
    Jan 6, 2017
    Posts:
    13
    I tested the shaders with float instead of fixed and that completely solved problem #2 (with the terrain). So far so good, thanks!

    The quality settings are the ones in the screenshot (green checkmark, and the pull down menu on the downward facing triangle has my custom layer selected). Texture compression is ASTC (recommended by Oculus), I also tried with no override originally and my first attempt to fix the problems was to switch to ASTC. Without override it should have been the compression used on desktop.

    It's not that clear from the screenshot in the OP, but the textures aren't overlit everywhere, more around the center of the camera (maybe some kind of specular effect?). Here's another screenshot that should better illustrate the problem:

    quest03.jpg
    I have the same highlight on desktop, but much smaller and less dull. After switching the platform to Android, it turned dull in the editor but it isn't that huge so it doesn't cover most of the near view. On the actual Android device it really is a problem since you can't tell the color of the tile bricks anymore.
     
  6. aleksandrk

    aleksandrk

    Unity Technologies

    Joined:
    Jul 3, 2017
    Posts:
    1,384
    There's another thing called Graphics Tiers. Can you check those?
     
  7. KayH

    KayH

    Joined:
    Jan 6, 2017
    Posts:
    13
  8. aleksandrk

    aleksandrk

    Unity Technologies

    Joined:
    Jul 3, 2017
    Posts:
    1,384
    By default Android will use Tier 2. Can you try and set the Standard Shader Quality to High?
     
  9. KayH

    KayH

    Joined:
    Jan 6, 2017
    Posts:
    13
    That fixed it, many thanks!
     
    aleksandrk likes this.
  10. edufireheart

    edufireheart

    Joined:
    Aug 6, 2017
    Posts:
    11
    I have a quite similar problem where I have a custom shader I created that works perfectly on my PC and also through Link, but when building and installing the apk in the Quest, it doesn't work anymore.

    Unfortunately for me that solution didn't work.

    To be more specific the shader works if I don't try to use any data coming from the tex2D function as return value for my frag function. Actually I realized I can use the function, but I can't use any data coming from there in the data that will be returned by frag, even if it works in my desktop and through Link.

    The code to the custom shader follows:
    Code (CSharp):
    1. // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
    2.  
    3. Shader "Custom/SphericalMaskDissolve1" {
    4.     Properties{
    5.         _TintColor("Tint Color", Color) = (0.5,0.5,0.5,0.5)
    6.         _MainTex("Particle Texture", 2D) = "white" {}
    7.         _InvFade("Soft Particles Factor", Range(0.01,3.0)) = 1.0
    8.  
    9.         _Glossiness("Smoothness", Range(0,1)) = 0.5
    10.         _Metallic("Metallic", Range(0,1)) = 0.0
    11.         [HDR]_Emission("Emission", Color) = (1,1,1,1)
    12.         _NoiseSize("Noise size", float) = 1
    13.     }
    14.  
    15.         Category{
    16.             Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" }
    17.             Blend SrcAlpha One
    18.             AlphaTest Greater .01
    19.             ColorMask RGB
    20.             Cull Off Lighting Off ZWrite Off Fog { Color(0,0,0,0) }
    21.             BindChannels {
    22.                 Bind "Color", color
    23.                 Bind "Vertex", vertex
    24.                 Bind "TexCoord", texcoord
    25.             }
    26.  
    27.             // ---- Fragment program cards
    28.             SubShader {
    29.                 Pass {
    30.  
    31.                     CGPROGRAM
    32.                     #pragma vertex vert
    33.                     #pragma fragment frag
    34.                     #pragma fragmentoption ARB_precision_hint_fastest
    35.                     #pragma multi_compile_particles
    36.  
    37.                     #include "UnityCG.cginc"
    38.  
    39.                     sampler2D _MainTex;
    40.                     fixed4 _TintColor;
    41.  
    42.                     half _Glossiness;
    43.                     half _Metallic;
    44.  
    45.                     fixed4 _Emission;
    46.                     float _NoiseSize;
    47.  
    48.                     float3 _GLOBALMaskPosition;
    49.                     half _GLOBALMaskRadius;
    50.                     half _GLOBALMaskSoftness;
    51.  
    52.                     struct appdata_t {
    53.                         float4 vertex : POSITION;
    54.                         fixed4 color : COLOR;
    55.                         float2 texcoord : TEXCOORD0;
    56.  
    57.                         float4 position : POSITION;//
    58.                     };
    59.  
    60.                     struct v2f {
    61.                         float4 vertex : POSITION;
    62.                         fixed4 color : COLOR;
    63.                         float2 texcoord : TEXCOORD0;
    64.                         float2 texcoord2 : TEXCOORD0;
    65.                         float4 worldSpacePos : TEXCOORD1;//
    66.                         #ifdef SOFTPARTICLES_ON
    67.                         float4 projPos : TEXCOORD1;
    68.                         #endif
    69.                     };
    70.  
    71.                     struct Input {
    72.                         float2 uv_MainTex;
    73.                         float3 worldPos;
    74.                     };
    75.  
    76.                     float4 _MainTex_ST;
    77.  
    78.                     v2f vert(appdata_t v)
    79.                     {
    80.                         v2f o;
    81.                         o.vertex = UnityObjectToClipPos(v.vertex);
    82.                         #ifdef SOFTPARTICLES_ON
    83.                         o.projPos = ComputeScreenPos(o.vertex);
    84.                         COMPUTE_EYEDEPTH(o.projPos.z);
    85.                         #endif
    86.                         o.color = v.color;
    87.                         o.texcoord = TRANSFORM_TEX(v.texcoord,_MainTex);
    88.  
    89.                         o.worldSpacePos = mul(unity_ObjectToWorld, v.position);//
    90.                         return o;
    91.                     }
    92.  
    93.                     sampler2D _CameraDepthTexture;
    94.                     float _InvFade;
    95.  
    96.                     fixed4 frag(v2f i) : COLOR
    97.                     {
    98.                         #ifdef SOFTPARTICLES_ON
    99.                         float sceneZ = LinearEyeDepth(UNITY_SAMPLE_DEPTH(tex2Dproj(_CameraDepthTexture, UNITY_PROJ_COORD(i.projPos))));
    100.                         float partZ = i.projPos.z;
    101.                         float fade = saturate(_InvFade * (sceneZ - partZ));
    102.                         i.color.a *= fade;
    103.                         #endif
    104.  
    105.                         half dist = distance(_GLOBALMaskPosition, i.worldSpacePos);//
    106.                         half sphere = 1 - saturate((dist - _GLOBALMaskRadius) / _GLOBALMaskSoftness);//
    107.                         //clip(sphere - 0.1);//
    108.  
    109.                         float4 textureColor = tex2D(_MainTex, i.texcoord);
    110.  
    111.                         return 2.0f * i.color * _TintColor * textureColor;
    112.                     }
    113.  
    114.  
    115.                     ENDCG
    116.                 }
    117.             }
    118.  
    119.             // ---- Dual texture cards
    120.             SubShader {
    121.                 Pass {
    122.                     SetTexture[_MainTex] {
    123.                         constantColor[_TintColor]
    124.                         combine constant * primary
    125.                     }
    126.                     SetTexture[_MainTex] {
    127.                         combine texture * previous DOUBLE
    128.                     }
    129.                 }
    130.             }
    131.  
    132.                         // ---- Single texture cards (does not do color tint)
    133.                         SubShader {
    134.                             Pass {
    135.                                 SetTexture[_MainTex] {
    136.                                     combine texture * primary
    137.                                 }
    138.                             }
    139.                         }
    140.         }
    141. }
    If I don't use "textureColor" in the return line of frag (even if storing it to a variable) it works the same way on Quest as on PC
     
  11. aleksandrk

    aleksandrk

    Unity Technologies

    Joined:
    Jul 3, 2017
    Posts:
    1,384
    @edufireheart no, it's a completely different problem.
    Try doing all you computations in float and check if this helps.
     
  12. edufireheart

    edufireheart

    Joined:
    Aug 6, 2017
    Posts:
    11
    Indeed it is a different problem but I was seeing it as not having a shader behaving the same way on Quest as it does on PC or through Oculus Link.

    Unfortunately the result is the same.

    Code (CSharp):
    1. // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
    2.  
    3. Shader "Custom/SphericalMaskDissolve1" {
    4.     Properties{
    5.         _TintColor("Tint Color", Color) = (0.5,0.5,0.5,0.5)
    6.         _MainTex("Particle Texture", 2D) = "white" {}
    7.         _InvFade("Soft Particles Factor", Range(0.01,3.0)) = 1.0
    8.  
    9.         _Glossiness("Smoothness", Range(0,1)) = 0.5
    10.         _Metallic("Metallic", Range(0,1)) = 0.0
    11.         [HDR]_Emission("Emission", Color) = (1,1,1,1)
    12.         _NoiseSize("Noise size", float) = 1
    13.     }
    14.  
    15.         Category{
    16.             Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" }
    17.             Blend SrcAlpha One
    18.             AlphaTest Greater .01
    19.             ColorMask RGB
    20.             Cull Off Lighting Off ZWrite Off Fog { Color(0,0,0,0) }
    21.             BindChannels {
    22.                 Bind "Color", color
    23.                 Bind "Vertex", vertex
    24.                 Bind "TexCoord", texcoord
    25.             }
    26.  
    27.             // ---- Fragment program cards
    28.             SubShader {
    29.                 Pass {
    30.  
    31.                     CGPROGRAM
    32.                     #pragma vertex vert
    33.                     #pragma fragment frag
    34.                     #pragma fragmentoption ARB_precision_hint_fastest
    35.                     #pragma multi_compile_particles
    36.  
    37.                     #include "UnityCG.cginc"
    38.  
    39.                     sampler2D _MainTex;
    40.                     fixed4 _TintColor;
    41.  
    42.                     half _Glossiness;
    43.                     half _Metallic;
    44.  
    45.                     fixed4 _Emission;
    46.                     float _NoiseSize;
    47.  
    48.                     float3 _GLOBALMaskPosition;
    49.                     half _GLOBALMaskRadius;
    50.                     half _GLOBALMaskSoftness;
    51.  
    52.                     struct appdata_t {
    53.                         float4 vertex : POSITION;
    54.                         //fixed4 color : COLOR;
    55.                         float4 color : COLOR;
    56.                         float2 texcoord : TEXCOORD0;
    57.  
    58.                         float4 position : POSITION;//
    59.                     };
    60.  
    61.                     struct v2f {
    62.                         float4 vertex : POSITION;
    63.                         //fixed4 color : COLOR;
    64.                         float4 color : COLOR;
    65.                         float2 texcoord : TEXCOORD0;
    66.                         float2 texcoord2 : TEXCOORD0;
    67.                         float4 worldSpacePos : TEXCOORD1;//
    68.                         #ifdef SOFTPARTICLES_ON
    69.                         float4 projPos : TEXCOORD1;
    70.                         #endif
    71.                     };
    72.  
    73.                     struct Input {
    74.                         float2 uv_MainTex;
    75.                         float3 worldPos;
    76.                     };
    77.  
    78.                     float4 _MainTex_ST;
    79.  
    80.                     v2f vert(appdata_t v)
    81.                     {
    82.                         v2f o;
    83.                         o.vertex = UnityObjectToClipPos(v.vertex);
    84.                         #ifdef SOFTPARTICLES_ON
    85.                         o.projPos = ComputeScreenPos(o.vertex);
    86.                         COMPUTE_EYEDEPTH(o.projPos.z);
    87.                         #endif
    88.                         o.color = v.color;
    89.                         o.texcoord = TRANSFORM_TEX(v.texcoord,_MainTex);
    90.  
    91.                         o.worldSpacePos = mul(unity_ObjectToWorld, v.position);//
    92.                         return o;
    93.                     }
    94.  
    95.                     sampler2D _CameraDepthTexture;
    96.                     float _InvFade;
    97.  
    98.  
    99.                     float4 frag(v2f i) : COLOR
    100.                     {
    101.                         #ifdef SOFTPARTICLES_ON
    102.                         float sceneZ = LinearEyeDepth(UNITY_SAMPLE_DEPTH(tex2Dproj(_CameraDepthTexture, UNITY_PROJ_COORD(i.projPos))));
    103.                         float partZ = i.projPos.z;
    104.                         float fade = saturate(_InvFade * (sceneZ - partZ));
    105.                         i.color.a *= fade;
    106.                         #endif
    107.  
    108.                         float4 textureColor = tex2D(_MainTex, i.texcoord);
    109.  
    110.                         //float4 temp = float4(textureColor.r, 1.0, 1.0, 1.0);
    111.  
    112.  
    113.  
    114.                         float4 temp = i.color;
    115.  
    116.                         temp.r = 1.0;
    117.                         temp.g = 0.0;
    118.                         temp.b = 0.0;
    119.  
    120.                         //temp.a = textureColor.a;
    121.  
    122.                         return temp;
    123.                     }  
    124.  
    125.                     ENDCG
    126.                 }
    127.             }
    128.  
    129.             // ---- Dual texture cards
    130.             SubShader {
    131.                 Pass {
    132.                     SetTexture[_MainTex] {
    133.                         constantColor[_TintColor]
    134.                         combine constant * primary
    135.                     }
    136.                     SetTexture[_MainTex] {
    137.                         combine texture * previous DOUBLE
    138.                     }
    139.                 }
    140.             }
    141.  
    142.                         // ---- Single texture cards (does not do color tint)
    143.                         SubShader {
    144.                             Pass {
    145.                                 SetTexture[_MainTex] {
    146.                                     combine texture * primary
    147.                                 }
    148.                             }
    149.                         }
    150.         }
    151. }
    In the code here I tried to change the color into a float4 and made it red in the frag function for testing purposes. When I uncomment the line with
    Code (CSharp):
    1. temp.a = textureColor.a;
    the shader doesn't behave anymore the same way it does in the Editor. Actually the result is as it took the texture and applied the _TintColor to it, instead of just being red as the frag function tells it to do.

    Is it something I'm getting wrong? Even if it is, it's quite strange to see it behaving well in the Editor and through Oculus Link (a simple red shader for testing) or on Quest when not returning values from tex2D but having _TintColor instead when having anything from tex2D in the returned value.
     
  13. edufireheart

    edufireheart

    Joined:
    Aug 6, 2017
    Posts:
    11
    From the code I shared above (only for testing purposes) I expected a red shader.

    How I see in the Editor and through Oculus Link:
    Capture d’écran (270).png

    How I see it on the Quest after I hit Build And Run:
    Capture d’écran (271).png
    (this happens whenever I use any value from tex2D as part of the returned value of the frag function)
     
  14. aleksandrk

    aleksandrk

    Unity Technologies

    Joined:
    Jul 3, 2017
    Posts:
    1,384
    Do you mind filing a bug report with this?
     
  15. edufireheart

    edufireheart

    Joined:
    Aug 6, 2017
    Posts:
    11
    Ok, I'll do that.

    Thanks for the help
     
unityunity