Search Unity

Question Simple shader doesn't work on Android

Discussion in 'Shaders' started by MonqoStudios, Aug 6, 2020.

  1. MonqoStudios

    MonqoStudios

    Joined:
    Oct 20, 2016
    Posts:
    22
    Hello all,

    I have a simple water shader that works perfectly fine on pc, but once I try to build it for mobile, the foam (that is an effect that floats on the water) appears to take over the complete shader or something (see pictures)

    Any ideas on how to fix this?

    What it is supposed to look like:

    upload_2020-8-6_12-8-59.png

    What it looks like when you switch to Android:
    upload_2020-8-6_12-13-44.png


    Shader:

    upload_2020-8-6_12-8-59.png upload_2020-8-6_12-13-44.png
    Code (CSharp):
    1. Shader "Roystan/Toon/Water"
    2. {
    3.     Properties
    4.     {
    5.         // What color the water will sample when the surface below is shallow.
    6.         _DepthGradientShallow("Depth Gradient Shallow", Color) = (0.325, 0.807, 0.971, 0.725)
    7.  
    8.         // What color the water will sample when the surface below is at its deepest.
    9.         _DepthGradientDeep("Depth Gradient Deep", Color) = (0.086, 0.407, 1, 0.749)
    10.  
    11.         // Maximum distance the surface below the water will affect the color gradient.
    12.         _DepthMaxDistance("Depth Maximum Distance", Float) = 1
    13.  
    14.         // Color to render the foam generated by objects intersecting the surface.
    15.         _FoamColor("Foam Color", Color) = (1,1,1,1)
    16.  
    17.         // Noise texture used to generate waves.
    18.         _SurfaceNoise("Surface Noise", 2D) = "white" {}
    19.  
    20.         // Speed, in UVs per second the noise will scroll. Only the xy components are used.
    21.         _SurfaceNoiseScroll("Surface Noise Scroll Amount", Vector) = (0.03, 0.03, 0, 0)
    22.  
    23.         // Values in the noise texture above this cutoff are rendered on the surface.
    24.         _SurfaceNoiseCutoff("Surface Noise Cutoff", Range(0, 1)) = 0.777
    25.  
    26.         // Red and green channels of this texture are used to offset the
    27.         // noise texture to create distortion in the waves.
    28.         _SurfaceDistortion("Surface Distortion", 2D) = "white" {}  
    29.  
    30.         // Multiplies the distortion by this value.
    31.         _SurfaceDistortionAmount("Surface Distortion Amount", Range(0, 1)) = 0.27
    32.  
    33.         // Control the distance that surfaces below the water will contribute
    34.         // to foam being rendered.
    35.         _FoamMaxDistance("Foam Maximum Distance", Float) = 0.4
    36.         _FoamMinDistance("Foam Minimum Distance", Float) = 0.04      
    37.     }
    38.     SubShader
    39.     {
    40.         Tags
    41.         {
    42.             "Queue" = "Transparent"
    43.         }
    44.  
    45.         Pass
    46.         {
    47.             // Transparent "normal" blending.
    48.             Blend SrcAlpha OneMinusSrcAlpha
    49.             ZWrite Off
    50.  
    51.             CGPROGRAM
    52.             #define SMOOTHSTEP_AA 0.01
    53.  
    54.             #pragma vertex vert
    55.             #pragma fragment frag
    56.  
    57.             #include "UnityCG.cginc"
    58.  
    59.             // Blends two colors using the same algorithm that our shader is using
    60.             // to blend with the screen. This is usually called "normal blending",
    61.             // and is similar to how software like Photoshop blends two layers.
    62.             float4 alphaBlend(float4 top, float4 bottom)
    63.             {
    64.                 float3 color = (top.rgb * top.a) + (bottom.rgb * (1 - top.a));
    65.                 float alpha = top.a + bottom.a * (1 - top.a);
    66.  
    67.                 return float4(color, alpha);
    68.             }
    69.  
    70.             struct appdata
    71.             {
    72.                 float4 vertex : POSITION;
    73.                 float4 uv : TEXCOORD0;
    74.                 float3 normal : NORMAL;
    75.             };
    76.  
    77.             struct v2f
    78.             {
    79.                 float4 vertex : SV_POSITION;  
    80.                 float2 noiseUV : TEXCOORD0;
    81.                 float2 distortUV : TEXCOORD1;
    82.                 float4 screenPosition : TEXCOORD2;
    83.                 float3 viewNormal : NORMAL;
    84.             };
    85.  
    86.             sampler2D _SurfaceNoise;
    87.             float4 _SurfaceNoise_ST;
    88.  
    89.             sampler2D _SurfaceDistortion;
    90.             float4 _SurfaceDistortion_ST;
    91.  
    92.             v2f vert (appdata v)
    93.             {
    94.                 v2f o;
    95.  
    96.                 o.vertex = UnityObjectToClipPos(v.vertex);
    97.                 o.screenPosition = ComputeScreenPos(o.vertex);
    98.                 o.distortUV = TRANSFORM_TEX(v.uv, _SurfaceDistortion);
    99.                 o.noiseUV = TRANSFORM_TEX(v.uv, _SurfaceNoise);
    100.                 o.viewNormal = COMPUTE_VIEW_NORMAL;
    101.  
    102.                 return o;
    103.             }
    104.  
    105.             float4 _DepthGradientShallow;
    106.             float4 _DepthGradientDeep;
    107.             float4 _FoamColor;
    108.  
    109.             float _DepthMaxDistance;
    110.             float _FoamMaxDistance;
    111.             float _FoamMinDistance;
    112.             float _SurfaceNoiseCutoff;
    113.             float _SurfaceDistortionAmount;
    114.  
    115.             float2 _SurfaceNoiseScroll;
    116.  
    117.             sampler2D _CameraDepthTexture;
    118.             sampler2D _CameraNormalsTexture;
    119.  
    120.             float4 frag (v2f i) : SV_Target
    121.             {
    122.                 // Retrieve the current depth value of the surface behind the
    123.                 // pixel we are currently rendering.
    124.                 float existingDepth01 = tex2Dproj(_CameraDepthTexture, UNITY_PROJ_COORD(i.screenPosition)).r;
    125.                 // Convert the depth from non-linear 0...1 range to linear
    126.                 // depth, in Unity units.
    127.                 float existingDepthLinear = LinearEyeDepth(existingDepth01);
    128.  
    129.                 // Difference, in Unity units, between the water's surface and the object behind it.
    130.                 float depthDifference = existingDepthLinear - i.screenPosition.w;
    131.  
    132.                 // Calculate the color of the water based on the depth using our two gradient colors.
    133.                 float waterDepthDifference01 = saturate(depthDifference / _DepthMaxDistance);
    134.                 float4 waterColor = lerp(_DepthGradientShallow, _DepthGradientDeep, waterDepthDifference01);
    135.                
    136.                 // Retrieve the view-space normal of the surface behind the
    137.                 // pixel we are currently rendering.
    138.                 float3 existingNormal = tex2Dproj(_CameraNormalsTexture, UNITY_PROJ_COORD(i.screenPosition));
    139.                
    140.                 // Modulate the amount of foam we display based on the difference
    141.                 // between the normals of our water surface and the object behind it.
    142.                 // Larger differences allow for extra foam to attempt to keep the overall
    143.                 // amount consistent.
    144.                 float3 normalDot = saturate(dot(existingNormal, i.viewNormal));
    145.                 float foamDistance = lerp(_FoamMaxDistance, _FoamMinDistance, normalDot);
    146.                 float foamDepthDifference01 = saturate(depthDifference / foamDistance);
    147.  
    148.                 float surfaceNoiseCutoff = foamDepthDifference01 * _SurfaceNoiseCutoff;
    149.  
    150.                 float2 distortSample = (tex2D(_SurfaceDistortion, i.distortUV).xy * 2 - 1) * _SurfaceDistortionAmount;
    151.  
    152.                 // Distort the noise UV based off the RG channels (using xy here) of the distortion texture.
    153.                 // Also offset it by time, scaled by the scroll speed.
    154.                 float2 noiseUV = float2((i.noiseUV.x + _Time.y * _SurfaceNoiseScroll.x) + distortSample.x,
    155.                 (i.noiseUV.y + _Time.y * _SurfaceNoiseScroll.y) + distortSample.y);
    156.                 float surfaceNoiseSample = tex2D(_SurfaceNoise, noiseUV).r;
    157.  
    158.                 // Use smoothstep to ensure we get some anti-aliasing in the transition from foam to surface.
    159.                 // Uncomment the line below to see how it looks without AA.
    160.                 // float surfaceNoise = surfaceNoiseSample > surfaceNoiseCutoff ? 1 : 0;
    161.                 float surfaceNoise = smoothstep(surfaceNoiseCutoff - SMOOTHSTEP_AA, surfaceNoiseCutoff + SMOOTHSTEP_AA, surfaceNoiseSample);
    162.  
    163.                 float4 surfaceNoiseColor = _FoamColor;
    164.                 surfaceNoiseColor.a *= surfaceNoise;
    165.  
    166.                 // Use normal alpha blending to combine the foam with the surface.
    167.                 return alphaBlend(surfaceNoiseColor, waterColor);
    168.             }
    169.             ENDCG
    170.         }
    171.     }
    172. }