Search Unity

Preclipped Shadows after Clip

Discussion in 'Shaders' started by liqid, Jan 7, 2021.

  1. liqid

    liqid

    Joined:
    Oct 4, 2016
    Posts:
    17
    Hello,

    I'm new to shaders and would like to create a shader that does what is visible on the right side of my attached image. Sadly I only am able to achieve what is visible on the left side.

    clipshadows.jpg

    I want to have the original cast shadows of my model, without the cast shadows being affected by the clipping.

    My current code is this:


    Code (CSharp):
    1. Shader "Custom/SeeThroughShader"
    2. {
    3.     Properties
    4.     {
    5.         _Color ("Color", Color) = (1,1,1,1)
    6.         _MainTex ("Albedo (RGB)", 2D) = "white" {}
    7.         _Glossiness ("Smoothness", Range(0,1)) = 0.5
    8.         _Metallic ("Metallic", Range(0,1)) = 0.0
    9.  
    10.     }
    11.     SubShader
    12.     {
    13.         Tags { "RenderType"="Opaque" }
    14.         LOD 200
    15.         CGPROGRAM
    16.         #pragma surface surf Standard fullforwardshadows addshadow
    17.         #pragma target 3.0
    18.  
    19.         sampler2D _MainTex;
    20.         float4 _PlayerPos;
    21.  
    22.         struct Input
    23.         {
    24.             float2 uv_MainTex;
    25.             float3 worldPos;
    26.         };
    27.  
    28.         half _Glossiness;
    29.         half _Metallic;
    30.         fixed4 _Color;
    31.  
    32.         void surf (Input IN, inout SurfaceOutputStandard o)
    33.         {
    34.             fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
    35.  
    36.             float dist = distance(IN.worldPos, _PlayerPos);
    37.  
    38.             if(dist<5) {
    39.                 clip(c- 0.99);
    40.             }
    41.  
    42.             o.Albedo = c.rgb;
    43.             o.Metallic = _Metallic;
    44.             o.Smoothness = _Glossiness;
    45.             o.Alpha = c.a;
    46.         }
    47.         ENDCG
    48.  
    49.     }
    50.  
    51.     FallBack "Diffuse"
    52. }
    53.  
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    The easiest solution is to duplicate your game object with the mesh. Set the current game object's mesh renderer to Cast Shadows > Off. Then make a copy of it, change the material to the default standard shader and Cast Shadows > Shadows Only.

    The shader only solution is to add some checks to see if A) The current render pass is the shadow caster pass and B) if the shadow caster pass is being used to render the depth texture or a shadow map.

    Knowing if it's the shadowcaster pass or not is trivial.
    Code (csharp):
    1. #if defined(UNITY_PASS_SHADOWCASTER)
    2. // this code will only exist in the shadow caster pass
    3. #endif
    Unfortunately, it's not as trivial to know if a shadow caster pass is being used for the camera depth texture (what Unity uses to receive directional shadows), or a shadow map. They both use the same pass. The best I've found so far is this:
    Code (csharp):
    1. #if defined(UNITY_PASS_SHADOWCASTER) // is a shadow caster or camera depth pass
    2. #if defined(SHADOWS_DEPTH) // is rendering the camera depth, directional shadow, or spot light shadow
    3. if (!any(unity_LightShadowBias))
    4. {
    5.   // is the camera depth texture, or a light with the shadow bias values set to 0 (don't do that!)
    6. }
    7. else
    8. {
    9.   // is a shadow map
    10. }
    11. #endif
    12. #endif
     
  3. liqid

    liqid

    Joined:
    Oct 4, 2016
    Posts:
    17
    Hey bgolus! Thanks so much for the swift reply. I tried you code and it worked! Basically I just added your code to the surf() function and then put the clip() function eveywhere, where its not the shadow map.

    Code (CSharp):
    1.             #if defined(UNITY_PASS_SHADOWCASTER) // is a shadow caster or camera depth pass
    2.             #if defined(SHADOWS_DEPTH) // is rendering the camera depth, directional shadow, or spot light shadow
    3.             if (!any(unity_LightShadowBias))
    4.             {
    5.               // is the camera depth texture, or a light with the shadow bias values set to 0 (don't do that!)
    6.                 if(dist<5) {
    7.                     clip(c- 0.99);
    8.                 }
    9.             }
    10.             else
    11.             {
    12.               // is a shadow map
    13.             }
    14.             #endif
    15.             #else
    16.                 if(dist<5) {
    17.                     clip(c- 0.99);
    18.                 }
    19.             #endif