Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Clip Shadows

Discussion in 'Shaders' started by 3d20Corp, Jan 9, 2016.

  1. 3d20Corp

    3d20Corp

    Joined:
    Sep 28, 2015
    Posts:
    5
    I am just starting to create shaders, and am using clip() to make part of my object transparent. My problem is that the clipped part still casts shadows. I am at a loss for how to make the transparent part of my object not cast shadows. Any help is very mush appreciated!
     
    JeffersonTD likes this.
  2. 3d20Corp

    3d20Corp

    Joined:
    Sep 28, 2015
    Posts:
    5
    Anyone at least point me in the right direction?
     
  3. BrianND

    BrianND

    Joined:
    May 14, 2015
    Posts:
    79
    I think Unity uses a separate pass with a tag called Tags { "LightMode" = "ShadowCaster" } to render shadows. To make "clipped" areas transparent you should just use or copy Transparent/Cutout shaders. Look at LegacyShaders/Transparent/Cutout/Diffuse shader source.
     
  4. jvo3dc

    jvo3dc

    Joined:
    Oct 11, 2013
    Posts:
    1,520
    Yes, and look around the forum, this question has been asked many times.
     
  5. 3d20Corp

    3d20Corp

    Joined:
    Sep 28, 2015
    Posts:
    5
    After digging around in the vertexlit cutout for a while, I finally got it. If anyone is interested, here's the shadow caster pass

    Code (CSharp):
    1.         Pass{
    2.         Name "Caster"
    3.         Tags{ "LightMode" = "ShadowCaster" }
    4.         Offset 1, 1
    5.  
    6.         Fog{ Mode Off }
    7.         ZWrite On ZTest LEqual Cull Off
    8.  
    9.         CGPROGRAM
    10. #pragma vertex vert
    11. #pragma fragment frag
    12. #pragma multi_compile_shadowcaster
    13. #include "UnityCG.cginc"
    14.  
    15.     struct v2f {
    16.         V2F_SHADOW_CASTER;
    17.         float2  uv : TEXCOORD1;
    18.         //float4 pos  : POSITION;
    19.         float3 wpos : TEXCOORD0;
    20.         float3 vpos : TEXCOORD2;
    21.     };
    22.  
    23.     struct Input {
    24.         float3 worldPos;
    25.     };
    26.  
    27.     uniform float4 _MainTex_ST;
    28.     float yBound;
    29.     float xBound;
    30.     v2f vert(appdata_base v)
    31.     {
    32.         v2f o;
    33.         TRANSFER_SHADOW_CASTER(o)
    34.             o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
    35.         o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
    36.         float3 worldPos = mul(_Object2World, v.vertex).xyz;
    37.         o.wpos = worldPos;
    38.         o.vpos = v.vertex.xyz;
    39.         return o;
    40.     }
    41.  
    42.     uniform sampler2D _MainTex;
    43.     uniform fixed _Cutoff;
    44.     uniform fixed4 _Color;
    45.  
    46.     float4 frag(v2f i) : SV_TARGET
    47.     {
    48.         fixed4 texcol = tex2D(_MainTex, i.uv);
    49.         clip(texcol.a*_Color.a - _Cutoff);
    50.         if (i.wpos.x < 0)
    51.         {
    52.             clip(-1);
    53.         }
    54.         if (i.wpos.z > yBound)
    55.         {
    56.             clip(-1);
    57.         }
    58.         if (i.wpos.x < 0)
    59.         {
    60.             clip(-1);
    61.         }
    62.         if (i.wpos.x > xBound)
    63.         {
    64.             clip(-1);
    65.         }
    66.  
    67.     SHADOW_CASTER_FRAGMENT(i)
    68.     }
    69.         ENDCG
    70.  
    71.     }
     
    JeffersonTD likes this.
  6. JeffersonTD

    JeffersonTD

    Joined:
    Feb 5, 2013
    Posts:
    267
    Thanks for sharing. I was also interested in this, and apparently the cutout shader(s) were indeed the place to look. I tried it (albeit I maybe don't need it any more as I've decided to go for an alternate solution for my project), and it indeed seems to work for clipping the shadows, but for some reason for me it had a weird striped side effect (see the "stripes" in the attachment). I wonder what the reason for that is. Anyone? Any ideas?

    But I do have a tip for you too. From what I've read earlier I think having conditions like that in a CG section is inefficient as it's run by the GPU. Calling clip multiple times may not be too good either. Someone who knows better may confirm, further specify or correct me if I'm wrong, but I think it would be more efficient to put that whole clipping iffing into one line of code using the min function.
     

    Attached Files:

  7. 3d20Corp

    3d20Corp

    Joined:
    Sep 28, 2015
    Posts:
    5
    Not sure about the stripes, as they don't show up in my shader. Probably some weird interaction with whatever other code you have in the shader. As for the conditionals I switched it to
    Code (CSharp):
    1.     if (i.wpos.x < 0 || i.wpos.x > xBound || i.wpos.z < 0 || i.wpos.z > yBound)
    2.     {
    3.         clip(-1);
    4.     }
    which cleans it up a lot, but not sure how I would do it outside the CG (I really still have no idea how shaders work), or how to do this with the min function.
     
  8. JeffersonTD

    JeffersonTD

    Joined:
    Feb 5, 2013
    Posts:
    267
    That is already much better: much cleaner, doesn't do multiple clips and doesn't necessarily need to go through all the conditions. I didn't mean that it would have to go outside the CG code, I just meant formulating the conditions as numbers (like xBound - i.wpos.x) and using the basic math function min for them. But what you wrote now might actually be better than the min solution - at least it's easier to read for a human. Which is computationally better may also depend on the probability of your conditions. It would be interesting to hear a comment from someone who understands the underlying architectural factors.

    I did a very quick check about the stripes and actually it seems that it is not related to just having the shadow caster code in my shader, it's related to the combination of that shadow caster code AND using the shader as a replacement shader. Once again, really confusing. o_O