Search Unity

How to make unlit shader that casts shadow?

Discussion in 'Shaders' started by Khai3, Mar 18, 2019.

  1. Khai3

    Khai3

    Joined:
    Aug 13, 2018
    Posts:
    16
    I know that unlit shadows by default cannot cast shadows.
    However, I need a shader that does not receive ambient light but is able to cast shadows. Does anyone know how to make such a shader?
    I am absolutely clueless when it comes to coding shaders sadly but I really do need this shader for my project.

    Thank you all.
     
  2. Johannski

    Johannski

    Joined:
    Jan 25, 2014
    Posts:
    826
    You need to either set a fallback shader that has a shadow caster pass or wirte your own shadow caster pass. Here is a simple unlit shader (with some fancy stencil support):

    Code (CSharp):
    1. Shader "Supyrb/Unlit/Texture"
    2. {
    3.     Properties
    4.     {
    5.         [HDR]_Color("Albedo", Color) = (1,1,1,1)
    6.         _MainTex ("Texture", 2D) = "white" {}
    7.        
    8.         [Header(Stencil)]
    9.         _Stencil ("Stencil ID [0;255]", Float) = 0
    10.         _ReadMask ("ReadMask [0;255]", Int) = 255
    11.         _WriteMask ("WriteMask [0;255]", Int) = 255
    12.         [Enum(UnityEngine.Rendering.CompareFunction)] _StencilComp ("Stencil Comparison", Int) = 0
    13.         [Enum(UnityEngine.Rendering.StencilOp)] _StencilOp ("Stencil Operation", Int) = 0
    14.         [Enum(UnityEngine.Rendering.StencilOp)] _StencilFail ("Stencil Fail", Int) = 0
    15.         [Enum(UnityEngine.Rendering.StencilOp)] _StencilZFail ("Stencil ZFail", Int) = 0
    16.        
    17.         [Header(Rendering)]
    18.         _Offset("Offset", float) = 0
    19.         [Enum(UnityEngine.Rendering.CullMode)] _Culling ("Cull Mode", Int) = 2
    20.         [Enum(Off,0,On,1)] _ZWrite("ZWrite", Int) = 1
    21.         [Enum(UnityEngine.Rendering.CompareFunction)] _ZTest ("ZTest", Int) = 4
    22.         [Enum(None,0,Alpha,1,Red,8,Green,4,Blue,2,RGB,14,RGBA,15)] _ColorMask("Color Mask", Int) = 15
    23.     }
    24.    
    25.     CGINCLUDE
    26.     #include "UnityCG.cginc"
    27.  
    28.     half4 _Color;
    29.     sampler2D _MainTex;
    30.     float4 _MainTex_ST;
    31.    
    32.     struct appdata
    33.     {
    34.         float4 vertex : POSITION;
    35.         float2 uv : TEXCOORD0;
    36.     };
    37.  
    38.     struct v2f
    39.     {
    40.         float2 uv : TEXCOORD0;
    41.         float4 vertex : SV_POSITION;
    42.     };
    43.  
    44.     v2f vert (appdata v)
    45.     {
    46.         v2f o;
    47.         o.vertex = UnityObjectToClipPos(v.vertex);
    48.         o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    49.         return o;
    50.     }
    51.    
    52.     half4 frag (v2f i) : SV_Target
    53.     {
    54.         return tex2D(_MainTex, i.uv) * _Color;
    55.     }
    56.     struct v2fShadow {
    57.         V2F_SHADOW_CASTER;
    58.         UNITY_VERTEX_OUTPUT_STEREO
    59.     };
    60.  
    61.     v2fShadow vertShadow( appdata_base v )
    62.     {
    63.         v2fShadow o;
    64.         UNITY_SETUP_INSTANCE_ID(v);
    65.         UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
    66.         TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
    67.         return o;
    68.     }
    69.  
    70.     float4 fragShadow( v2fShadow i ) : SV_Target
    71.     {
    72.         SHADOW_CASTER_FRAGMENT(i)
    73.     }
    74.    
    75.     ENDCG
    76.        
    77.     SubShader
    78.     {
    79.         Stencil
    80.         {
    81.             Ref [_Stencil]
    82.             ReadMask [_ReadMask]
    83.             WriteMask [_WriteMask]
    84.             Comp [_StencilComp]
    85.             Pass [_StencilOp]
    86.             Fail [_StencilFail]
    87.             ZFail [_StencilZFail]
    88.         }
    89.        
    90.         Pass
    91.         {
    92.             Tags { "RenderType"="Opaque" "Queue" = "Geometry" }
    93.             LOD 100
    94.             Cull [_Culling]
    95.             Offset [_Offset], [_Offset]
    96.             ZWrite [_ZWrite]
    97.             ZTest [_ZTest]
    98.             ColorMask [_ColorMask]
    99.            
    100.             CGPROGRAM
    101.             #pragma target 3.0
    102.             #pragma vertex vert
    103.             #pragma fragment frag
    104.             ENDCG
    105.         }
    106.        
    107.         // Pass to render object as a shadow caster
    108.         Pass
    109.         {
    110.             Name "ShadowCaster"
    111.             Tags { "LightMode" = "ShadowCaster" }
    112.             LOD 80
    113.             Cull [_Culling]
    114.             Offset [_Offset], [_Offset]
    115.             ZWrite [_ZWrite]
    116.             ZTest [_ZTest]
    117.            
    118.             CGPROGRAM
    119.             #pragma vertex vertShadow
    120.             #pragma fragment fragShadow
    121.             #pragma target 2.0
    122.             #pragma multi_compile_shadowcaster
    123.             ENDCG
    124.         }
    125.     }
    126. }
    127.  
    The important part is the last pass :)
     
  3. Khai3

    Khai3

    Joined:
    Aug 13, 2018
    Posts:
    16
    Thanks so much man. Really appreciate you taking your time to help me.
    Gonna try this out soon.:D
     
  4. materialvision

    materialvision

    Joined:
    Dec 13, 2018
    Posts:
    1
    Thank you for this! Works great. But... what about receiving shadows... is that more difficult? Basically I have a cartoon like character witch is "unlit" in style, but still would be good if it received and casts shadows. Any ideas?
     
  5. toomasio

    toomasio

    Joined:
    Nov 19, 2013
    Posts:
    198
    In the built-in shaders you can get something similar under Nature/Tree Soft Occlusion Leaves...if you dont feel like importing custom stuff.
     
    Ton111, A_Marraff and devstudent14 like this.
  6. onionface

    onionface

    Joined:
    Dec 25, 2012
    Posts:
    11
    Hey,
    I'm currently looking for the same thing, wondering if you find a solution?
     
  7. Przemyslaw_Zaworski

    Przemyslaw_Zaworski

    Joined:
    Jun 9, 2017
    Posts:
    328
    Unlit textured with shadow receiving and shadow casting:

    Code (CSharp):
    1. Shader "UnlitWithShadows"
    2. {
    3.     Properties
    4.     {
    5.         _TextureMap ("Texture", 2D) = "" {}
    6.     }
    7.     SubShader
    8.     {
    9.         Pass
    10.         {
    11.             Tags {"LightMode" = "ForwardBase"}
    12.             CGPROGRAM
    13.             #pragma vertex VSMain
    14.             #pragma fragment PSMain
    15.             #pragma multi_compile_fwdbase
    16.             #include "AutoLight.cginc"
    17.            
    18.             sampler2D _TextureMap;
    19.  
    20.             struct SHADERDATA
    21.             {
    22.                 float4 position : SV_POSITION;
    23.                 float2 uv : TEXCOORD0;
    24.                 float4 _ShadowCoord : TEXCOORD1;
    25.             };
    26.  
    27.             float4 ComputeScreenPos (float4 p)
    28.             {
    29.                 float4 o = p * 0.5;
    30.                 return float4(float2(o.x, o.y*_ProjectionParams.x) + o.w, p.zw);
    31.             }
    32.  
    33.             SHADERDATA VSMain (float4 vertex:POSITION, float2 uv:TEXCOORD0)
    34.             {
    35.                 SHADERDATA vs;
    36.                 vs.position = UnityObjectToClipPos(vertex);
    37.                 vs.uv = uv;
    38.                 vs._ShadowCoord = ComputeScreenPos(vs.position);
    39.                 return vs;
    40.             }
    41.  
    42.             float4 PSMain (SHADERDATA ps) : SV_TARGET
    43.             {
    44.                 return lerp(float4(0,0,0,1), tex2D(_TextureMap, ps.uv), step(0.5, SHADOW_ATTENUATION(ps)));
    45.             }
    46.            
    47.             ENDCG
    48.         }
    49.        
    50.         Pass
    51.         {
    52.             Tags{ "LightMode" = "ShadowCaster" }
    53.             CGPROGRAM
    54.             #pragma vertex VSMain
    55.             #pragma fragment PSMain
    56.  
    57.             float4 VSMain (float4 vertex:POSITION) : SV_POSITION
    58.             {
    59.                 return UnityObjectToClipPos(vertex);
    60.             }
    61.  
    62.             float4 PSMain (float4 vertex:SV_POSITION) : SV_TARGET
    63.             {
    64.                 return 0;
    65.             }
    66.            
    67.             ENDCG
    68.         }
    69.     }
    70. }
    71.  
     
  8. mowax74

    mowax74

    Joined:
    Mar 3, 2015
    Posts:
    97
    This works very well, exactly what i needed. Thank you.
     
  9. Groupustule

    Groupustule

    Joined:
    Jun 28, 2020
    Posts:
    11
    How would you change the code to attenuate the shadow?
    I tried changing the alpha value on line 44 (in the lerp) without success. The shaddow remains a perfect black.
    Thanks in advance.
     
  10. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,342
    swingingtom likes this.
  11. Groupustule

    Groupustule

    Joined:
    Jun 28, 2020
    Posts:
    11
    Sorry for the delay: thanks bgolus, I used one of the shaders provided in the tutos and it more or less works. I will keep going with the rest of the game programing and get back to the shader part once everything is done (shaders programing is just not my thing...).
     
  12. Vkev

    Vkev

    Joined:
    Jul 21, 2020
    Posts:
    4
    i truggle this for like 10 hour, thank you so much. This work even in the 2023 version of unity
     
    Przemyslaw_Zaworski likes this.
  13. Rugbug_Redfern

    Rugbug_Redfern

    Joined:
    Jun 2, 2017
    Posts:
    20
    I modified the shader to let you change the brightness of the shadow.




    Code (CSharp):
    1. Shader"UnlitWithShadows"
    2. {
    3.     Properties
    4.     {
    5.         _TextureMap ("Texture", 2D) = "" {}
    6.         _TileAmount ("Scale Multiplier", float) = 1
    7.         _ShadowBrightness ("Shadow Brightness", Range(0, 1)) = 0
    8.     }
    9.     SubShader
    10.     {
    11.         Pass
    12.         {
    13.             Tags {"LightMode" = "ForwardBase"}
    14.             CGPROGRAM
    15.             #pragma vertex VSMain
    16.             #pragma fragment PSMain
    17.             #pragma multi_compile_fwdbase
    18. #include "AutoLight.cginc"
    19.          
    20. sampler2D _TextureMap;
    21. float _TileAmount;
    22. float _ShadowBrightness;
    23. struct SHADERDATA
    24. {
    25.     float4 position : SV_POSITION;
    26.     float2 uv : TEXCOORD0;
    27.     float4 _ShadowCoord : TEXCOORD1;
    28. };
    29. float4 ComputeScreenPos(float4 p)
    30. {
    31.     float4 o = p * 0.5;
    32.     return float4(float2(o.x, o.y * _ProjectionParams.x) + o.w, p.zw);
    33. }
    34. SHADERDATA VSMain(float4 vertex : POSITION, float2 uv : TEXCOORD0)
    35. {
    36.     SHADERDATA vs;
    37.     vs.position = UnityObjectToClipPos(vertex);
    38.     vs.uv = uv;
    39.     vs._ShadowCoord = ComputeScreenPos(vs.position);
    40.     return vs;
    41. }
    42. float4 PSMain(SHADERDATA ps) : SV_TARGET
    43. {
    44.     float4 col = tex2D(_TextureMap, ps.uv * _TileAmount);
    45.     return lerp(col * float4(_ShadowBrightness, _ShadowBrightness, _ShadowBrightness, 1), col, step(0.5, SHADOW_ATTENUATION(ps)));
    46. }
    47.          
    48.             ENDCG
    49.         }
    50.      
    51.         Pass
    52.         {
    53.             Tags{ "LightMode" = "ShadowCaster" }
    54.             CGPROGRAM
    55.             #pragma vertex VSMain
    56.             #pragma fragment PSMain
    57. float4 VSMain(float4 vertex : POSITION) : SV_POSITION
    58. {
    59.     return UnityObjectToClipPos(vertex);
    60. }
    61. float4 PSMain(float4 vertex : SV_POSITION) : SV_TARGET
    62. {
    63.     return 0;
    64. }
    65.          
    66.             ENDCG
    67.         }
    68.     }
    69. }
    70.  
     
    JohannesNienaber likes this.
  14. JohannesNienaber

    JohannesNienaber

    Joined:
    Dec 3, 2012
    Posts:
    7
    Good stuff!
     
  15. SandwichDevelopment

    SandwichDevelopment

    Joined:
    Sep 8, 2022
    Posts:
    17
    What would the Tags {"LightMode" = "ForwardBase"} in the first pass be in URP?
     
  16. Przemyslaw_Zaworski

    Przemyslaw_Zaworski

    Joined:
    Jun 9, 2017
    Posts:
    328
    "LightMode"="SRPDefaultUnlit"

    Unlit URP with shadow casting:

    Code (CSharp):
    1. Shader "UnlitURP"
    2. {
    3.     Properties
    4.     {
    5.         _BaseMap ("Texture", 2D) = "white" {}
    6.         [HideInInspector] _Cull("__cull", Float) = 2.0
    7.     }
    8.     SubShader
    9.     {
    10.         Tags
    11.         {
    12.             "RenderPipeline" = "UniversalPipeline"
    13.             "RenderType" = "Opaque"
    14.             "Queue" = "Geometry"
    15.             "UniversalMaterialType" = "Lit"
    16.             "IgnoreProjector" = "True"
    17.         }
    18.  
    19.         HLSLINCLUDE
    20.         #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
    21.  
    22.         CBUFFER_START(UnityPerMaterial)
    23.         float4 _BaseMap_ST;
    24.         float4 _BaseColor;
    25.         float _Cutoff;  
    26.         CBUFFER_END
    27.         ENDHLSL
    28.  
    29.         Pass
    30.         {
    31.             Name "Unlit"
    32.             Tags { "LightMode"="SRPDefaultUnlit" }
    33.             HLSLPROGRAM
    34.             #pragma vertex VSMain
    35.             #pragma fragment PSMain
    36.             #pragma shader_feature _ALPHATEST_ON
    37.  
    38.             struct Attributes
    39.             {
    40.                 float4 vertex    : POSITION;
    41.                 float2 uv        : TEXCOORD0;
    42.                 float4 color    : COLOR;
    43.             };
    44.  
    45.             struct Varyings
    46.             {
    47.                 float4 vertex     : SV_POSITION;
    48.                 float2 uv        : TEXCOORD0;
    49.                 float4 color    : COLOR;
    50.             };
    51.          
    52.             TEXTURE2D(_BaseMap);
    53.             SAMPLER(sampler_BaseMap);
    54.  
    55.             Varyings VSMain(Attributes IN)
    56.             {
    57.                 Varyings OUT;
    58.                 OUT.vertex = TransformObjectToHClip(IN.vertex.xyz);
    59.                 OUT.uv = IN.uv;
    60.                 OUT.color = IN.color;
    61.                 return OUT;
    62.             }
    63.  
    64.             float4 PSMain(Varyings IN) : SV_Target
    65.             {
    66.                 float2 uv = IN.uv.xy  * _BaseMap_ST.xy + _BaseMap_ST.zw;
    67.                 return _BaseMap.Sample(sampler_BaseMap, uv);
    68.             }
    69.             ENDHLSL
    70.         }
    71.  
    72.         Pass
    73.         {
    74.             Name "ShadowCaster"
    75.             Tags { "LightMode"="ShadowCaster" }
    76.             ZWrite On
    77.             ZTest LEqual
    78.             ColorMask 0
    79.             Cull[_Cull]
    80.  
    81.             HLSLPROGRAM
    82.             #pragma vertex ShadowPassVertex
    83.             #pragma fragment ShadowPassFragment
    84.             #pragma shader_feature _ALPHATEST_ON
    85.             #pragma shader_feature _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
    86.             #pragma multi_compile_instancing
    87.             #pragma multi_compile_vertex _ _CASTING_PUNCTUAL_LIGHT_SHADOW
    88.             #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl"
    89.             #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/SurfaceInput.hlsl"
    90.             #include "Packages/com.unity.render-pipelines.universal/Shaders/ShadowCasterPass.hlsl"
    91.             ENDHLSL
    92.         }
    93.  
    94.         Pass
    95.         {
    96.             Name "DepthOnly"
    97.             Tags { "LightMode"="DepthOnly" }
    98.             ColorMask 0
    99.             ZWrite On
    100.             ZTest LEqual
    101.  
    102.             HLSLPROGRAM
    103.             #pragma vertex DepthOnlyVertex
    104.             #pragma fragment DepthOnlyFragment
    105.             #pragma shader_feature _ALPHATEST_ON
    106.             #pragma shader_feature _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
    107.             #pragma multi_compile_instancing
    108.             #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl"
    109.             #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/SurfaceInput.hlsl"
    110.             #include "Packages/com.unity.render-pipelines.universal/Shaders/DepthOnlyPass.hlsl"
    111.             ENDHLSL
    112.         }
    113.  
    114.         Pass
    115.         {
    116.             Name "DepthNormals"
    117.             Tags { "LightMode"="DepthNormals" }
    118.             ZWrite On
    119.             ZTest LEqual
    120.  
    121.             HLSLPROGRAM
    122.             #pragma vertex DepthNormalsVertex
    123.             #pragma fragment DepthNormalsFragment
    124.             #pragma shader_feature_local _NORMALMAP
    125.             #pragma shader_feature _ALPHATEST_ON
    126.             #pragma shader_feature _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
    127.             #pragma multi_compile_instancing
    128.             #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl"
    129.             #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/SurfaceInput.hlsl"
    130.             #include "Packages/com.unity.render-pipelines.universal/Shaders/DepthNormalsPass.hlsl"
    131.             ENDHLSL
    132.         }
    133.     }
    134. }
     
  17. SandwichDevelopment

    SandwichDevelopment

    Joined:
    Sep 8, 2022
    Posts:
    17
    Would it be possible for it to receive shadows too?
     
  18. SandwichDevelopment

    SandwichDevelopment

    Joined:
    Sep 8, 2022
    Posts:
    17
    I've been looking all over and could not find a solution. How do I make it receive shadows?