Search Unity

clip() in surface shader doesn't clip ligthing.

Discussion in 'Shaders' started by Sosowski, May 10, 2017.

  1. Sosowski

    Sosowski

    Joined:
    May 20, 2013
    Posts:
    5
    I'm trying to make a simple cutout surface shader in forward rendering (VR) and even tho the pixels are clipping properly, I am left with a shadow pass, regardless whether receiving shadows is on or off for the given mesh (if I disable cast shadows, I get similar shadow-z-issue result but there are no shadowed spots)
    I'm using 5.5.1f

    Here's the shader and a screenshot:

    Code (csharp):
    1.  
    2. Shader "Custom/Playershader" {
    3.     Properties {
    4.         _Color ("Color", Color) = (1,1,1,1)
    5.         _MainTex ("Albedo (RGB)", 2D) = "white" {}
    6.         _NoiseTex("Noise", 2D) = "white" {}
    7.         _Glossiness ("Smoothness", Range(0,1)) = 0.5
    8.         _Metallic ("Metallic", Range(0,1)) = 0.0
    9.     }
    10.     SubShader {
    11.         Cull Off
    12.         Tags { "Queue" = "AlphaTest" "IgnoreProjector" = "True"  "RenderType"="TransparentCutout" }
    13.         LOD 200
    14.        
    15.         CGPROGRAM
    16.         // Physically based Standard lighting model, and enable shadows on all light types
    17.         #pragma surface surf Standard fullforwardshadows
    18.  
    19.         // Use shader model 3.0 target, to get nicer looking lighting
    20.         #pragma target 3.0
    21.  
    22.         sampler2D _MainTex;
    23.         sampler2D _NoiseTex;
    24.  
    25.         struct Input {
    26.             float2 uv_MainTex;
    27.             float3 worldPos;
    28.         };
    29.  
    30.         half _Glossiness;
    31.         half _Metallic;
    32.         fixed4 _Color;
    33.  
    34.         void surf (Input IN, inout SurfaceOutputStandard o) {
    35.             // Albedo comes from a texture tinted by color
    36.             fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
    37.             fixed4 noise = tex2D(_NoiseTex, IN.uv_MainTex);
    38.             o.Albedo = c.rgb;
    39.             // Metallic and smoothness come from slider variables
    40.             o.Metallic = _Metallic;
    41.             o.Smoothness = _Glossiness;
    42.             //o.Alpha = c.a;
    43.             float3 cam = _WorldSpaceCameraPos - IN.worldPos;
    44.             //cam.y *= 10.0;
    45.             float threshold = 4.2f + noise.r*.515;
    46.            
    47.             o.Albedo *= length(cam) - threshold;
    48.             clip(length(cam) - threshold);
    49.             //o.Alpha = .5f;// distance(_WorldSpaceCameraPos, IN.worldPos);
    50.  
    51.         }
    52.         ENDCG
    53.     }
    54.     FallBack "Diffuse"
    55. }
    56.  
    57.  
     
  2. Johannski

    Johannski

    Joined:
    Jan 25, 2014
    Posts:
    826
    Try to change the Fallback to
    Code (CSharp):
    1. Fallback "Legacy Shaders/Transparent/Cutout/VertexLit"
    Otherwise you might need to write your own shadow caster pass. This is the one from the fallback shader as a reference:

    Code (CSharp):
    1. // Pass to render object as a shadow caster
    2.     Pass {
    3.         Name "Caster"
    4.         Tags { "LightMode" = "ShadowCaster" }
    5.        
    6. CGPROGRAM
    7. #pragma vertex vert
    8. #pragma fragment frag
    9. #pragma target 2.0
    10. #pragma multi_compile_shadowcaster
    11. #pragma multi_compile_instancing // allow instanced shadow pass for most of the shaders
    12. #include "UnityCG.cginc"
    13.  
    14. struct v2f {
    15.     V2F_SHADOW_CASTER;
    16.     float2  uv : TEXCOORD1;
    17.     UNITY_VERTEX_OUTPUT_STEREO
    18. };
    19.  
    20. uniform float4 _MainTex_ST;
    21.  
    22. v2f vert( appdata_base v )
    23. {
    24.     v2f o;
    25.     UNITY_SETUP_INSTANCE_ID(v);
    26.     UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
    27.     TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
    28.     o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
    29.     return o;
    30. }
    31.  
    32. uniform sampler2D _MainTex;
    33. uniform fixed _Cutoff;
    34. uniform fixed4 _Color;
    35.  
    36. float4 frag( v2f i ) : SV_Target
    37. {
    38.     fixed4 texcol = tex2D( _MainTex, i.uv );
    39.     clip( texcol.a*_Color.a - _Cutoff );
    40.    
    41.     SHADOW_CASTER_FRAGMENT(i)
    42. }
    43. ENDCG
    44.  
    45.     }
     
  3. tomekkie2

    tomekkie2

    Joined:
    Jul 6, 2012
    Posts:
    973
    Try it again with render queue changed from AlphaTest to Transparent in your shader.
     
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,339
    Or just add addshadow to the #pragma surface line and let the surface shader generate the appropriate shadow pass for you.
     
    shelim, plmx and chingwa like this.
  5. tomekkie2

    tomekkie2

    Joined:
    Jul 6, 2012
    Posts:
    973
    Great thanks, I had a similiar case with my shaders and that really helped.
     
  6. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,339
    For simple alpha test where the alpha of the _MainTex is the only factor, @Johannski 's Fallback example should work, but for anything more complex than that you likely need a custom shadowcaster pass (which controls both the shadow casting and directional light shadow receiving). Luckily that addshadow can do that for you, as it'll add a shadowcaster pass that uses the same surf function as the rest of the shader.

    However, it is important to be mindful of that fact that the shadowcaster is used for both shadow casting and shadow receiving as sometimes what you want for those two cases are not the same, and there's not a really good way to differentiate between the two.