Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

please help with transparency issue (shadow casting/receiving sprite shader)

Discussion in 'Shaders' started by JoeStrout, Jun 18, 2017.

  1. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    I need sprites to both cast and receive shadows, and I'm oh so close, as you can see in this test scene.



    The multi-colored circle there is using my custom shader, and as you can see, it is receiving a shadow from the cylinder in front of it. It is also casting a shadow on the plane behind.

    But the transparent areas of my sprites are doing weird things. In the image above, the purple sprite is a standard sprite (using the Sprites-Default shader) positioned behind my test sprite. But everywhere my test sprite (which is using "full rect" mode for its mesh) appears, the purple sprite behind it can't be seen... we see only the 3D plane and sky instead.

    Moreover, the transparent areas are both casting and receiving shadows, which they should not do. And finally, I can't see the shadow on the plane behind the transparent areas.

    If I switch my test sprite from "full rect" to "tight" mode, the problem is less apparent...



    ...but of course it's still there. And in my real game, I can't always use tight meshes. So I really need those transparent areas to be fully transparent — not cast shadows, not receive shadows, and not mess up the drawing of stuff behind them.

    Here's my shader code.

    Code (CSharp):
    1. // Unlit shader that nonetheless receives shadows.
    2. // Adapted from: http://answers.unity3d.com/questions/1187379
    3. Shader "Unlit/Custom/Unlit Transparent Shadow Receiver" {
    4.      Properties {
    5.          _Color ("Main Color", Color) = (1,1,1,1)
    6.          _MainTex ("Base (RGB)", 2D) = "white" {}
    7.      }
    8.      SubShader {
    9.          Tags {"Queue" = "Geometry" "IgnoreProjector"="True" "RenderType" = "Transparent"}
    10.          Cull Off
    11.          ZWrite On
    12.          Blend SrcAlpha OneMinusSrcAlpha
    13. // ------------------------------------------------------------------
    14. //  Shadow rendering pass
    15. Pass {
    16.     Name "ShadowCaster"
    17.     Tags { "LightMode" = "ShadowCaster" }
    18.  
    19.     ZWrite On ZTest LEqual Cull Off
    20.  
    21.     CGPROGRAM
    22.     #pragma target 2.0
    23.  
    24.     #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
    25.     #pragma skip_variants SHADOWS_SOFT
    26.     #pragma multi_compile_shadowcaster
    27.  
    28.     #pragma vertex vertShadowCaster
    29.     #pragma fragment fragShadowCaster
    30.  
    31.     #include "UnityStandardShadow.cginc"
    32.  
    33.     ENDCG
    34. }
    35.          Pass {
    36.              Tags { "LightMode" = "ForwardBase" }    // handles main directional light, vertex/SH lights, and lightmaps
    37.              CGPROGRAM
    38.                  #pragma vertex vert
    39.                  #pragma fragment frag
    40.                  #pragma multi_compile_fwdbase
    41.                  #pragma fragmentoption ARB_fog_exp2
    42.                  #pragma fragmentoption ARB_precision_hint_fastest
    43.                
    44.                  #include "UnityCG.cginc"
    45.                  #include "AutoLight.cginc"
    46.                
    47.                  struct v2f
    48.                  {
    49.                      float4    pos            : SV_POSITION;
    50.                      float2    uv            : TEXCOORD0;
    51.                      LIGHTING_COORDS(1,2)
    52.                  };
    53.                  float4 _MainTex_ST;
    54.                  v2f vert (appdata_tan v)
    55.                  {
    56.                      v2f o;
    57.                    
    58.                      o.pos = mul( UNITY_MATRIX_MVP, v.vertex);
    59.                      o.uv = TRANSFORM_TEX (v.texcoord, _MainTex).xy;
    60.                      TRANSFER_VERTEX_TO_FRAGMENT(o);
    61.                      return o;
    62.                  }
    63.                  sampler2D _MainTex;
    64.                  fixed4 frag(v2f i) : COLOR
    65.                  {
    66.                      //fixed atten = LIGHT_ATTENUATION(i);    // Light attenuation + shadows.
    67.                      fixed atten = SHADOW_ATTENUATION(i); // Shadows ONLY.
    68.                      fixed4 tex = tex2D(_MainTex, i.uv);
    69.                      fixed4 c = tex * atten;    // attenuate color
    70.                      c.a = tex.a;                // don't attenuate alpha
    71.                      return c;
    72.                  }
    73.              ENDCG
    74.          }
    75.           Pass {
    76.              Tags {"LightMode" = "ForwardAdd"}    // handles per-pixel additive lights (called once per such light)
    77.              Blend One One
    78.              CGPROGRAM
    79.                  #pragma vertex vert
    80.                  #pragma fragment frag
    81.                  #pragma multi_compile_fwdadd_fullshadows
    82.                  #pragma fragmentoption ARB_fog_exp2
    83.                  #pragma fragmentoption ARB_precision_hint_fastest
    84.                
    85.                  #include "UnityCG.cginc"
    86.                  #include "AutoLight.cginc"
    87.                
    88.                  struct v2f
    89.                  {
    90.                      float4    pos            : SV_POSITION;
    91.                      float2    uv            : TEXCOORD0;
    92.                      LIGHTING_COORDS(1,2)
    93.                  };
    94.                  float4 _MainTex_ST;
    95.                  v2f vert (appdata_tan v)
    96.                  {
    97.                      v2f o;
    98.                    
    99.                      o.pos = mul( UNITY_MATRIX_MVP, v.vertex);
    100.                      o.uv = TRANSFORM_TEX (v.texcoord, _MainTex).xy;
    101.                      TRANSFER_VERTEX_TO_FRAGMENT(o);
    102.                      return o;
    103.                  }
    104.                  sampler2D _MainTex;
    105.                  fixed4 frag(v2f i) : COLOR
    106.                  {
    107.                     // fixed atten = LIGHT_ATTENUATION(i);    // Light attenuation + shadows.
    108.                      fixed atten = SHADOW_ATTENUATION(i); // Shadows ONLY.
    109.                      fixed4 tex = tex2D(_MainTex, i.uv);
    110.                      fixed4 c = tex * atten;    // attenuate color
    111.                      c.a = tex.a;                // don't attenuate alpha
    112.                      return c;
    113.                  }
    114.              ENDCG
    115.          }
    116.      }
    117.      FallBack "VertexLit"
    118. }
    I'm hoping it's something simple — some way to check the alpha bail out without any effect at all, even on the depth buffer. I'm sure the problem is somewhere in this pass:



    ...but I just don't see how to fix it. Any pointers would be greatly appreciated.
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    Your shadowcaster pass is using this line:

    #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON

    That tells a shader that it needs to compile a new variant if one of those keywords is enabled on the shader, but it doesn't actually enable or disable any of them. So instead that shadow caster pass is just compiling the default opaque version as nothing in the shader properties are allowing you to toggle on any of those keywords, and I doubt you're enabling it via script.

    So you can enable alpha testing if you remove that line and replace it with:

    #define _ALPHATEST_ON

    And now it ... still won't work as you're missing a required property, _Cutoff, so add this to your properties:

    [HideInInspector] _Cutoff ("", Float) = 0.5

    It should also be noted there's really no need to add the custom shadowcaster pass, the real fix should be use the correct fallback shader. (You'll still need the _Cutoff).

    Fallback "Legacy Shaders/Transparent/Cutout/VertexLit"
     
    HenryLiN0118 and JoeStrout like this.
  3. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    First, thanks so much for replying — this stuff is still very arcane to me.

    These changes are definitely some progress. The shadows now cast (and are received) properly, on only the areas where the alpha is past the cutoff. But the remaining transparent areas are still somehow mucking up drawing of stuff behind it.



    Stepping through the rendering with the Frame Debugger, I no longer see anything suspicious on step 3, or any other step, except the very last one — "Draw Dynamic" in the Render.TransparentGeometry pass — where the purple sprite is drawn, and it simply doesn't draw in the area of my custom sprite. But nothing in the previous steps gives me any clue why that would be.

    Here's the revised shader code.

    Code (CSharp):
    1. // Unlit shader that nonetheless receives shadows.
    2. // Adapted from: http://answers.unity3d.com/questions/1187379
    3. // With help from: http://forum.unity3d.com/threads/477358/
    4. Shader "Unlit/Custom/Unlit Transparent Shadow Receiver" {
    5.      Properties {
    6.         _Color ("Main Color", Color) = (1,1,1,1)
    7.         _MainTex ("Base (RGB)", 2D) = "white" {}
    8.         _Cutoff ("Cutoff", Float) = 0.5
    9.      }
    10.      SubShader {
    11.          Tags {"Queue" = "Geometry" "IgnoreProjector"="True" "RenderType" = "Transparent"}
    12.          Cull Off
    13.          ZWrite On
    14.          Blend SrcAlpha OneMinusSrcAlpha
    15.          Pass {
    16.              Tags { "LightMode" = "ForwardBase" }    // handles main directional light, vertex/SH lights, and lightmaps
    17.              CGPROGRAM
    18.                  #pragma vertex vert
    19.                  #pragma fragment frag
    20.                  #pragma multi_compile_fwdbase
    21.                  #pragma fragmentoption ARB_fog_exp2
    22.                  #pragma fragmentoption ARB_precision_hint_fastest
    23.                
    24.                  #include "UnityCG.cginc"
    25.                  #include "AutoLight.cginc"
    26.                
    27.                  struct v2f
    28.                  {
    29.                      float4    pos            : SV_POSITION;
    30.                      float2    uv            : TEXCOORD0;
    31.                      LIGHTING_COORDS(1,2)
    32.                  };
    33.                  float4 _MainTex_ST;
    34.                  v2f vert (appdata_tan v)
    35.                  {
    36.                      v2f o;
    37.                    
    38.                      o.pos = mul( UNITY_MATRIX_MVP, v.vertex);
    39.                      o.uv = TRANSFORM_TEX (v.texcoord, _MainTex).xy;
    40.                      TRANSFER_VERTEX_TO_FRAGMENT(o);
    41.                      return o;
    42.                  }
    43.                  sampler2D _MainTex;
    44.                  fixed4 frag(v2f i) : COLOR
    45.                  {
    46.                      //fixed atten = LIGHT_ATTENUATION(i);    // Light attenuation + shadows.
    47.                      fixed atten = SHADOW_ATTENUATION(i); // Shadows ONLY.
    48.                      fixed4 tex = tex2D(_MainTex, i.uv);
    49.                      fixed4 c = tex * atten;    // attenuate color
    50.                      c.a = tex.a;                // don't attenuate alpha
    51.                      return c;
    52.                  }
    53.              ENDCG
    54.          }
    55.           Pass {
    56.              Tags {"LightMode" = "ForwardAdd"}    // handles per-pixel additive lights (called once per such light)
    57.              Blend One One
    58.              CGPROGRAM
    59.                  #pragma vertex vert
    60.                  #pragma fragment frag
    61.                  #pragma multi_compile_fwdadd_fullshadows
    62.                  #pragma fragmentoption ARB_fog_exp2
    63.                  #pragma fragmentoption ARB_precision_hint_fastest
    64.                
    65.                  #include "UnityCG.cginc"
    66.                  #include "AutoLight.cginc"
    67.                
    68.                  struct v2f
    69.                  {
    70.                      float4    pos            : SV_POSITION;
    71.                      float2    uv            : TEXCOORD0;
    72.                      LIGHTING_COORDS(1,2)
    73.                  };
    74.                  float4 _MainTex_ST;
    75.                  v2f vert (appdata_tan v)
    76.                  {
    77.                      v2f o;
    78.                    
    79.                      o.pos = mul( UNITY_MATRIX_MVP, v.vertex);
    80.                      o.uv = TRANSFORM_TEX (v.texcoord, _MainTex).xy;
    81.                      TRANSFER_VERTEX_TO_FRAGMENT(o);
    82.                      return o;
    83.                  }
    84.                  sampler2D _MainTex;
    85.                  fixed4 frag(v2f i) : COLOR
    86.                  {
    87.                     // fixed atten = LIGHT_ATTENUATION(i);    // Light attenuation + shadows.
    88.                      fixed atten = SHADOW_ATTENUATION(i); // Shadows ONLY.
    89.                      fixed4 tex = tex2D(_MainTex, i.uv);
    90.                      fixed4 c = tex * atten;    // attenuate color
    91.                      c.a = tex.a;                // don't attenuate alpha
    92.                      return c;
    93.                  }
    94.              ENDCG
    95.          }
    96.      }
    97.     Fallback "Legacy Shaders/Transparent/Cutout/VertexLit"
    98. }
    Any idea what might still be awry?

    Thanks again,
    - Joe
     
  4. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    I think I've got it! :D

    The secret was to use the clip function in the fragment function, to bail out entirely on any pixels whose alpha is below the cutoff value. Documentation on this little trick appears to be weak, at least in the context of Unity, but my google-fu today was strong. ;)

    So finally I got the desired result:



    ...and, here's the revised shader code:

    Code (CSharp):
    1. // Unlit shader that nonetheless receives shadows.
    2. // Adapted from: http://answers.unity3d.com/questions/1187379
    3. // With help from: http://forum.unity3d.com/threads/477358/
    4. Shader "Unlit/Custom/Unlit Cutoff Shadow Savvy" {
    5. Properties {
    6.         _Color ("Main Color", Color) = (1,1,1,1)
    7.         _MainTex ("Base (RGB)", 2D) = "white" {}
    8.         _Cutoff ("Cutoff", Float) = 0.5
    9.     }
    10.     SubShader {
    11.         Tags {"Queue" = "Geometry" "IgnoreProjector"="True" "RenderType" = "Transparent"}
    12.         Cull Off
    13.         ZWrite On
    14.         Blend SrcAlpha OneMinusSrcAlpha
    15.        
    16.         Pass {
    17.             Tags { "LightMode" = "ForwardBase" }    // handles main directional light, vertex/SH lights, and lightmaps
    18.             CGPROGRAM
    19.             #pragma vertex vert
    20.             #pragma fragment frag
    21.             #pragma multi_compile_fwdbase
    22.             #pragma fragmentoption ARB_fog_exp2
    23.             #pragma fragmentoption ARB_precision_hint_fastest
    24.            
    25.             #include "UnityCG.cginc"
    26.             #include "AutoLight.cginc"
    27.    
    28.             float4 _MainTex_ST;
    29.             sampler2D _MainTex;
    30.             float _Cutoff;
    31.  
    32.             struct v2f {
    33.                 float4    pos            : SV_POSITION;
    34.                 float2    uv            : TEXCOORD0;
    35.                 LIGHTING_COORDS(1,2)
    36.             };
    37.            
    38.             v2f vert (appdata_tan v) {
    39.                 v2f o;
    40.                
    41.                 o.pos = mul( UNITY_MATRIX_MVP, v.vertex);
    42.                 o.uv = TRANSFORM_TEX (v.texcoord, _MainTex).xy;
    43.                 TRANSFER_VERTEX_TO_FRAGMENT(o);
    44.                 return o;
    45.             }
    46.                    
    47.             fixed4 frag(v2f i) : COLOR {
    48.                 fixed4 tex = tex2D(_MainTex, i.uv);
    49.                
    50.                 // If alpha is less than _Cutoff, then bail out on this pixel entirely
    51.                 // (don't even write to the depth buffer).
    52.                 clip(tex.a - _Cutoff);
    53.  
    54.                 fixed atten = SHADOW_ATTENUATION(i); // Attenuation for shadows ONLY.
    55.                 fixed4 c = tex * atten;        // attenuate color
    56.                 c.a = tex.a;                // don't attenuate alpha
    57.                 return c;
    58.             }
    59.             ENDCG
    60.         }
    61.         Pass {
    62.             Tags {"LightMode" = "ForwardAdd"}    // handles per-pixel additive lights (called once per such light)
    63.             Blend One One
    64.             CGPROGRAM
    65.             #pragma vertex vert
    66.             #pragma fragment frag
    67.             #pragma multi_compile_fwdadd_fullshadows
    68.             #pragma fragmentoption ARB_fog_exp2
    69.             #pragma fragmentoption ARB_precision_hint_fastest
    70.            
    71.             #include "UnityCG.cginc"
    72.             #include "AutoLight.cginc"
    73.            
    74.             struct v2f {
    75.                 float4    pos            : SV_POSITION;
    76.                 float2    uv            : TEXCOORD0;
    77.                 LIGHTING_COORDS(1,2)
    78.             };
    79.            
    80.             float4 _MainTex_ST;
    81.             sampler2D _MainTex;
    82.             float _Cutoff;
    83.            
    84.             v2f vert (appdata_tan v) {
    85.                 v2f o;
    86.                
    87.                 o.pos = mul( UNITY_MATRIX_MVP, v.vertex);
    88.                 o.uv = TRANSFORM_TEX (v.texcoord, _MainTex).xy;
    89.                 TRANSFER_VERTEX_TO_FRAGMENT(o);
    90.                 return o;
    91.             }
    92.            
    93.             fixed4 frag(v2f i) : COLOR {
    94.                 fixed4 tex = tex2D(_MainTex, i.uv);
    95.                
    96.                 // If alpha is less than _Cutoff, then bail out on this pixel entirely
    97.                 // (don't even write to the depth buffer).
    98.                 clip(tex.a - _Cutoff);
    99.  
    100.                 fixed atten = SHADOW_ATTENUATION(i); // Attenuation for shadows ONLY.
    101.                 fixed4 c = tex * atten;        // attenuate color
    102.                 c.a = tex.a;                // don't attenuate alpha
    103.                 return c;
    104.  
    105.             }
    106.             ENDCG
    107.         }
    108.     }
    109.     Fallback "Legacy Shaders/Transparent/Cutout/VertexLit"
    110. }
    If anybody else needs sprites that cast and receive shadows, here you go! And of course if anybody can spot any further improvements to this shader, please don't be shy about saying so.

    Thank you @bgolus for getting me unstuck today!
     
  5. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Oops. Not quite all happy now. There is still one issue remaining:

    Shadows don't appear on my sprites when they are flipped.

    They still cast shadows just fine (assuming I've set the renderer to cast double-sided shadows). But they don't receive shadows.

    I'm hoping there is a simple shader property or pragma I can set that might fix this... but I already have "Cull off"... so I'm not sure what to try. Any ideas?
     
  6. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    It is a simple as Cull Off, but only if you have a shadow caster pass in your shader. If you copy the code from the cutout vertex lit shader and add Cull Off it should fix the problem.
     
  7. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Shadow caster pass? Even though my problem is in receiving shadows, and not in casting them?
     
  8. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    Yes. The main directional light's shadows are actually "received" by the camera depth texture rather than during the forward pass. The camera depth texture is created using the shadow caster pass. In Unity 4 there were separate shadow caster and shadow receiver passes, but they've been merged into one for Unity 5.
     
    JoeStrout likes this.
  9. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Awesome, thanks for the explanation.

    Again in the spirit of giving back to the community, here's my updated shader... both casts and receives shadows, even when flipped.

    Code (csharp):
    1. // Unlit shader that nonetheless receives shadows.
    2. // Adapted from: http://answers.unity3d.com/questions/1187379
    3. // With help from: http://forum.unity3d.com/threads/477358/
    4. Shader "Unlit/Custom/Unlit Cutoff Shadow Savvy" {
    5. Properties {
    6.         _Color ("Main Color", Color) = (1,1,1,1)
    7.         _MainTex ("Base (RGB)", 2D) = "white" {}
    8.         _Cutoff ("Cutoff", Float) = 0.5
    9.     }
    10.     SubShader {
    11.         Tags {"Queue" = "Geometry" "IgnoreProjector"="True" "RenderType" = "Transparent"}
    12.         Cull Off
    13.         ZWrite On
    14.         Blend SrcAlpha OneMinusSrcAlpha
    15.        
    16.         Pass {
    17.             Tags { "LightMode" = "ForwardBase" }    // handles main directional light, vertex/SH lights, and lightmaps
    18.             CGPROGRAM
    19.             #pragma vertex vert
    20.             #pragma fragment frag
    21.             #pragma multi_compile_fwdbase
    22.             #pragma fragmentoption ARB_fog_exp2
    23.             #pragma fragmentoption ARB_precision_hint_fastest
    24.            
    25.             #include "UnityCG.cginc"
    26.             #include "AutoLight.cginc"
    27.    
    28.             float4 _MainTex_ST;
    29.             sampler2D _MainTex;
    30.             float _Cutoff;
    31.  
    32.             struct v2f {
    33.                 float4    pos            : SV_POSITION;
    34.                 float2    uv            : TEXCOORD0;
    35.                 LIGHTING_COORDS(1,2)
    36.             };
    37.            
    38.             v2f vert (appdata_tan v) {
    39.                 v2f o;
    40.                
    41.                 o.pos = UnityObjectToClipPos( v.vertex);
    42.                 o.uv = TRANSFORM_TEX (v.texcoord, _MainTex).xy;
    43.                 TRANSFER_VERTEX_TO_FRAGMENT(o);
    44.                 return o;
    45.             }
    46.                    
    47.             fixed4 frag(v2f i) : COLOR {
    48.                 fixed4 tex = tex2D(_MainTex, i.uv);
    49.                
    50.                 // If alpha is less than _Cutoff, then bail out on this pixel entirely
    51.                 // (don't even write to the depth buffer).
    52.                 clip(tex.a - _Cutoff);
    53.  
    54.                 fixed atten = SHADOW_ATTENUATION(i); // Attenuation for shadows ONLY.
    55.                 fixed4 c = tex * atten;        // attenuate color
    56.                 c.a = tex.a;                // don't attenuate alpha
    57.                 return c;
    58.             }
    59.             ENDCG
    60.         }
    61.         Pass {
    62.             Tags {"LightMode" = "ForwardAdd"}    // handles per-pixel additive lights (called once per such light)
    63.             Blend One One
    64.             CGPROGRAM
    65.             #pragma vertex vert
    66.             #pragma fragment frag
    67.             #pragma multi_compile_fwdadd_fullshadows
    68.             #pragma fragmentoption ARB_fog_exp2
    69.             #pragma fragmentoption ARB_precision_hint_fastest
    70.            
    71.             #include "UnityCG.cginc"
    72.             #include "AutoLight.cginc"
    73.            
    74.             struct v2f {
    75.                 float4    pos            : SV_POSITION;
    76.                 float2    uv            : TEXCOORD0;
    77.                 LIGHTING_COORDS(1,2)
    78.             };
    79.            
    80.             float4 _MainTex_ST;
    81.             sampler2D _MainTex;
    82.             float _Cutoff;
    83.            
    84.             v2f vert (appdata_tan v) {
    85.                 v2f o;
    86.                
    87.                 o.pos = UnityObjectToClipPos( v.vertex);
    88.                 o.uv = TRANSFORM_TEX (v.texcoord, _MainTex).xy;
    89.                 TRANSFER_VERTEX_TO_FRAGMENT(o);
    90.                 return o;
    91.             }
    92.            
    93.             fixed4 frag(v2f i) : COLOR {
    94.                 fixed4 tex = tex2D(_MainTex, i.uv);
    95.                
    96.                 // If alpha is less than _Cutoff, then bail out on this pixel entirely
    97.                 // (don't even write to the depth buffer).
    98.                 clip(tex.a - _Cutoff);
    99.  
    100.                 fixed atten = SHADOW_ATTENUATION(i); // Attenuation for shadows ONLY.
    101.                 fixed4 c = tex * atten;        // attenuate color
    102.                 c.a = tex.a;                // don't attenuate alpha
    103.                 return c;
    104.  
    105.             }
    106.             ENDCG
    107.         }
    108.        
    109.         // Pass to render object as a shadow caster (and receiver)
    110.         Pass {
    111.             Name "Caster"
    112.             Tags { "LightMode" = "ShadowCaster" }
    113.            
    114.             CGPROGRAM
    115.             #pragma vertex vert
    116.             #pragma fragment frag
    117.             #pragma target 2.0
    118.             #pragma multi_compile_shadowcaster
    119.             #pragma multi_compile_instancing // allow instanced shadow pass for most of the shaders
    120.             #include "UnityCG.cginc"
    121.    
    122.             struct v2f {
    123.                 V2F_SHADOW_CASTER;
    124.                 float2  uv : TEXCOORD1;
    125.                 UNITY_VERTEX_OUTPUT_STEREO
    126.             };
    127.    
    128.             uniform float4 _MainTex_ST;
    129.    
    130.             v2f vert( appdata_base v )
    131.             {
    132.                 v2f o;
    133.                 UNITY_SETUP_INSTANCE_ID(v);
    134.                 UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
    135.                 TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
    136.                 o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
    137.                 return o;
    138.             }
    139.    
    140.             uniform sampler2D _MainTex;
    141.             uniform fixed _Cutoff;
    142.             uniform fixed4 _Color;
    143.    
    144.             float4 frag( v2f i ) : SV_Target
    145.             {
    146.                 fixed4 texcol = tex2D( _MainTex, i.uv );
    147.                 clip( texcol.a*_Color.a - _Cutoff );
    148.        
    149.                 SHADOW_CASTER_FRAGMENT(i)
    150.             }
    151.             ENDCG
    152.    
    153.         }
    154.  
    155.     }
    156.     Fallback "Legacy Shaders/Transparent/Cutout/VertexLit"
    157. }
     
    Arvaaperekele likes this.
  10. SpiralCircus

    SpiralCircus

    Joined:
    Feb 1, 2014
    Posts:
    34
    That clip(tex.a - _Cutoff) thing just fixed an unrelated problem for me that was driving me crazy. Thanks for posting your code.
     
  11. DanRP

    DanRP

    Joined:
    May 26, 2013
    Posts:
    33
    Thank you JoeStrout for sharing this shader. It works beautifully with 1 directional light. However, when I have 2 or more directional lights, the sprite actually starts to light up.

    Below is an example with 1 directional light from the front, left. The sprite is rendering at its native brightness (i.e. it appears unlit) with correct shadows.


    Below is the same as above except with a second directional light in the back. The shadows are rendering properly, but the sprite now appears much brighter.


    Below is the same as above except with a third directional light added. The shadows are rendering properly, but the sprite now appears way brighter and is almost blown out in the back.


    Can you help me to pinpoint the shader code that is causing this? Presumably it's in the "Tags {"LightMode" = "ForwardAdd"}" section of the shader.

    Thanks for any help you can provide!
    Dan
     
  12. DanRP

    DanRP

    Joined:
    May 26, 2013
    Posts:
    33
    FYI: I found a bit of a workaround for now.

    I replaced both instances of this line:
    fixed4 tex = tex2D(_MainTex, i.uv);

    with:
    fixed4 tex = tex2D(_MainTex, i.uv) * _Color;

    Now, I can use the shader's Main Color slider to turn down the brightness so that it matches its unlit level.

    Hope this helps,
    Dan
     
    JoeStrout likes this.
  13. Koshkacherepashka

    Koshkacherepashka

    Joined:
    Mar 24, 2017
    Posts:
    2
    Hello, i can use it it get me this error: " Parse error: syntax error, unexpected $end, expecting TOK_SHADER " can anybody help?(((