Skip to content

Instantly share code, notes, and snippets.

@NathoSteveo
Last active August 23, 2023 13:50

Revisions

  1. NathoSteveo revised this gist Aug 23, 2023. No changes.
  2. NathoSteveo revised this gist Aug 23, 2023. 1 changed file with 6 additions and 15 deletions.
    21 changes: 6 additions & 15 deletions SHADOW_OUTLINE.shader
    Original file line number Diff line number Diff line change
    @@ -12,10 +12,9 @@ Shader"NATHO/SHADOW_OUTLINE"
    Properties
    {
    _MainTex ("Texture", 2D) = "white" {}
    _AOTex ("Ambient Occlusion", 2D) = "white" {}
    _NormalMap ("Normal Map", 2D) = "bump" {}
    _OutlineColor ("Outline color", Color) = (0, 0, 0, 1)
    _ShadowColour("Shadow Color", Color) = (0, 0, 0, 1)
    _AOStrength ("AO Strength", Range(0, 1)) = 0.5
    _ShadowStrength ("Shadow Strength", Range(0, 1)) = 0.2
    _ShadowStep ("Shadow Amount", Range(0, 1)) = 0.1
    _ShadowDilation ("Outline Size", Range(0, 10)) = 1
    @@ -70,8 +69,6 @@ Shader"NATHO/SHADOW_OUTLINE"

    sampler2D _MainTex;
    float4 _MainTex_ST;
    sampler2D _AOTex;
    float _AOStrength;
    float3 _ShadowColour;

    Varyings vert(Attributes IN)
    @@ -84,6 +81,7 @@ Shader"NATHO/SHADOW_OUTLINE"

    VertexNormalInputs normalInput = GetVertexNormalInputs(IN.normal);
    OUT.normalWS = normalInput.normalWS;

    OUT.uv = TRANSFORM_TEX(IN.uv, _MainTex);

    return OUT;
    @@ -95,7 +93,7 @@ Shader"NATHO/SHADOW_OUTLINE"
    static float2 sobelSamplePoints[9] =
    {
    float2(-1, 1), float2(0, 1), float2(1, 1),
    float2(-1, 0), float2(0, 0), float2(1, 1),
    float2(-1, 0), float2(0, 0), float2(1, 0),
    float2(-1, -1), float2(0, -1), float2(1, -1)
    };

    @@ -147,7 +145,6 @@ Shader"NATHO/SHADOW_OUTLINE"
    float4 frag(Varyings IN) : SV_Target
    {
    float4 texColor = tex2D(_MainTex, IN.uv);
    float ao = tex2D(_AOTex, IN.uv).r;
    float4 colour = _Colour;

    //[ Calculate light direction for the main light ]
    @@ -165,28 +162,22 @@ Shader"NATHO/SHADOW_OUTLINE"
    float4 shadowCoord = TransformWorldToShadowCoord(IN.posWS);
    float shadowMap = MainLightRealtimeShadow(shadowCoord);

    //float NdotL = saturate(dot(_MainLightPosition.xyz, IN.normalWS));
    float NdotL = saturate(dot(IN.normalWS, _MainLightPosition));

    float combinedShadow = min(NdotL, shadowMap);
    //float shadowValue = saturate(step(_ShadowStep, combinedShadow) + _ShadowStrength);
    float shadowValue = saturate(combinedShadow + _ShadowStrength);

    //float finalShadowValue = shadowValue * (1.0 - _AOStrength) + ao * _AOStrength;
    float finalShadowValue = lerp(shadowValue, ao, _AOStrength);

    float shadowOutlineMask = ShadowSobelOperator(shadowCoord, _ShadowDilation / pow(2, shadowCoord.w));
    shadowOutlineMask *= 1.0 - smoothstep(_ShadowStep - 0.1, _ShadowStep, shadowMap);
    shadowOutlineMask *= step(_ShadowStep, NdotL);

    float3 coloredShadow = _ShadowColour.xyz;
    float3 col = texColor.rgb * finalShadowValue;
    float3 col = texColor.rgb * shadowValue;

    col += coloredShadow * (1.0 - finalShadowValue);
    col += coloredShadow * (1.0 - shadowValue);
    col = lerp(col, _OutlineColor.rgb, saturate(shadowOutlineMask));

    //float3 finalColor = lightCol * col;
    float3 finalColor = lightCol * col;
    float3 finalColor = col * lightCol;

    return float4(finalColor, 1);
    }
  3. NathoSteveo revised this gist Aug 22, 2023. 1 changed file with 185 additions and 127 deletions.
    312 changes: 185 additions & 127 deletions SHADOW_OUTLINE.shader
    Original file line number Diff line number Diff line change
    @@ -1,154 +1,210 @@
    Shader "Unlit/SHADOW_OUTLINE"
    /*
    ███╗░░██╗░█████╗░████████╗██╗░░██╗░█████╗░  ░██████╗████████╗███████╗██╗░░░██╗███████╗░█████╗░
    ████╗░██║██╔══██╗╚══██╔══╝██║░░██║██╔══██╗  ██╔════╝╚══██╔══╝██╔════╝██║░░░██║██╔════╝██╔══██╗
    ██╔██╗██║███████║░░░██║░░░███████║██║░░██║  ╚█████╗░░░░██║░░░█████╗░░╚██╗░██╔╝█████╗░░██║░░██║
    ██║╚████║██╔══██║░░░██║░░░██╔══██║██║░░██║  ░╚═══██╗░░░██║░░░██╔══╝░░░╚████╔╝░██╔══╝░░██║░░██║
    ██║░╚███║██║░░██║░░░██║░░░██║░░██║╚█████╔╝  ██████╔╝░░░██║░░░███████╗░░╚██╔╝░░███████╗╚█████╔╝
    ╚═╝░░╚══╝╚═╝░░╚═╝░░░╚═╝░░░╚═╝░░╚═╝░╚════╝░  ╚═════╝░░░░╚═╝░░░╚══════╝░░░╚═╝░░░╚══════╝░╚════╝░
    */
    //-------------------------------------------------------------------------------[ OPEN WORLD ]
    Shader"NATHO/SHADOW_OUTLINE"
    {
    Properties
    {
    _MainTex ("Texture", 2D) = "white" {}
    //_AOTex ("Ambient Occlusion", 2D) = "white" {}
    _ShadowStep ("Shadow step value", Range(0, 1)) = 0.1
    _ShadowMin ("Minimum shadow value", Range(0, 1)) = 0.2
    _AOTex ("Ambient Occlusion", 2D) = "white" {}
    _OutlineColor ("Outline color", Color) = (0, 0, 0, 1)
    _ShadowDilation ("Shadow dilation", Range(0, 10)) = 1
    _ShadowColour("Shadow Color", Color) = (0, 0, 0, 1)
    _AOStrength ("AO Strength", Range(0, 1)) = 0.5
    _ShadowStrength ("Shadow Strength", Range(0, 1)) = 0.2
    _ShadowStep ("Shadow Amount", Range(0, 1)) = 0.1
    _ShadowDilation ("Outline Size", Range(0, 10)) = 1
    }

    SubShader
    {
    Tags { "RenderType"="Opaque" }
    LOD 200
    Tags
    {
    "RenderType" = "Opaque"
    "RenderPipeline" = "UniversalPipeline"
    "UniversalMaterialType" = "Lit"
    "IgnoreProjector" = "True"
    }
    LOD 300

    //[ FORWARD LIT ]
    Pass
    {
    {
    Name "ForwardLit"
    Tags { "LightMode" = "UniversalForward" }
    Tags
    {
    "LightMode" = "UniversalForward"
    }

    HLSLPROGRAM
    #pragma target 3.0
    #pragma vertex vert
    #pragma fragment frag

    #pragma multi_compile _ _MAIN_LIGHT_SHADOWS
    #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
    #pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS
    #pragma multi_compile _ _SHADOWS_SOFT

    #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
    #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"

    struct Attributes
    {
    float4 vertex : POSITION;
    float3 normal : NORMAL;
    float2 uv : TEXCOORD0;
    };
    struct Attributes
    {
    float4 vertex : POSITION;
    float3 normal : NORMAL;
    float2 uv : TEXCOORD0;
    };

    struct Varyings
    {
    float4 posCS : SV_POSITION;
    float3 posWS : TEXCOORD0;
    float3 normalWS : TEXCOORD1;
    float2 uv : TEXCOORD2;
    };
    struct Varyings
    {
    float4 posCS : SV_POSITION;
    float3 posWS : TEXCOORD0;
    float3 normalWS : TEXCOORD1;
    float2 uv : TEXCOORD2;
    };

    sampler2D _MainTex;
    float4 _MainTex_ST;
    sampler2D _AOTex;
    float _AOStrength;
    float3 _ShadowColour;

    Varyings vert(Attributes IN)
    {
    Varyings OUT;

    sampler2D _MainTex;
    float4 _MainTex_ST;
    sampler2D _AOTex;
    VertexPositionInputs vertexInput = GetVertexPositionInputs(IN.vertex);
    OUT.posCS = vertexInput.positionCS;
    OUT.posWS = vertexInput.positionWS;

    Varyings vert(Attributes IN)
    {
    Varyings OUT;
    VertexPositionInputs vertexInput = GetVertexPositionInputs(IN.vertex.xyz);
    OUT.posCS = vertexInput.positionCS;
    OUT.posWS = vertexInput.positionWS;
    VertexNormalInputs normalInput = GetVertexNormalInputs(IN.normal);
    OUT.normalWS = normalInput.normalWS;
    OUT.uv = TRANSFORM_TEX(IN.uv, _MainTex);

    VertexNormalInputs normalInput = GetVertexNormalInputs(IN.normal);
    OUT.normalWS = normalInput.normalWS;

    OUT.uv = TRANSFORM_TEX(IN.uv, _MainTex);
    return OUT;
    }

    return OUT;
    }
    float _ShadowStep, _ShadowStrength, _ShadowDilation;
    float3 _OutlineColor;

    float _ShadowStep, _ShadowMin, _ShadowDilation;
    float3 _OutlineColor;
    static float2 sobelSamplePoints[9] =
    {
    float2(-1, 1), float2(0, 1), float2(1, 1),
    float2(-1, 0), float2(0, 0), float2(1, 1),
    float2(-1, -1), float2(0, -1), float2(1, -1)
    };

    // 3x3 sample points
    static float2 sobelSamplePoints[9] = {
    float2(-1, 1), float2(0, 1), float2(1, 1),
    float2(-1, 0), float2(0, 0), float2(1, 0),
    float2(-1, -1), float2(0, -1), float2(1, -1)
    };
    static float sobelXKernel[9] =
    {
    1, 0, -1,
    2, 0, -2,
    1, 0, -1
    };

    static float sobelXKernel[9] = {
    1, 0, -1,
    2, 0, -2,
    1, 0, -1
    };
    static float sobelYKernel[9] =
    {
    1, 2, 1,
    0, 0, 0,
    -1, -2, -1
    };

    // Calculate the Sobel operator of the shadowmap
    float ShadowSobelOperator(float4 shadowCoord, float dilation)
    {
    // Get the shadowmap texel size
    ShadowSamplingData shadowSamplingData = GetMainLightShadowSamplingData();
    float4 shadowMap_TexelSize = shadowSamplingData.shadowmapSize;
    // Initialise results
    float sobelX = 0;
    float sobelY = 0;
    // Loop over sample points
    [unroll] for (int i = 0; i < 9; i++)
    {
    // Sample shadowmap
    float shadowImage = MainLightRealtimeShadow(float4(shadowCoord.xy + sobelSamplePoints[i] * dilation * shadowMap_TexelSize.xy, shadowCoord.zw));

    static float sobelYKernel[9] = {
    1, 2, 1,
    0, 0, 0,
    -1, -2, -1
    };
    // Sum the convolution values
    sobelX += shadowImage * sobelXKernel[i];
    sobelY += shadowImage * sobelYKernel[i];
    }
    // Return the magnitude
    return sqrt(sobelX * sobelX + sobelY * sobelY);
    }

    float3 Lambert(float3 lightColor, float3 lightDir, float3 normal)
    {
    float NdotL = saturate(dot(normal, lightDir));
    return lightColor;
    }

    // Calculate the Sobel operator of the shadowmap
    float ShadowSobelOperator(float4 shadowCoord, float dilation)
    float4 _Colour;
    //[ FRAG ]
    float4 frag(Varyings IN) : SV_Target
    {
    float4 texColor = tex2D(_MainTex, IN.uv);
    float ao = tex2D(_AOTex, IN.uv).r;
    float4 colour = _Colour;

    //[ Calculate light direction for the main light ]
    float3 lightPos = _MainLightPosition.xyz;
    //[ Lambertian lighting calculation for the main light ]
    float3 lightCol = Lambert(_MainLightColor * unity_LightData.z, lightPos, IN.normalWS);

    uint lightsCount = GetAdditionalLightsCount();
    for (int j = 0; j < lightsCount; j++)
    {
    // Get the shadowmap texelsize
    ShadowSamplingData shadowSamplingData = GetMainLightShadowSamplingData();
    float4 shadowMap_TexelSize = shadowSamplingData.shadowmapSize;

    // Initialise results
    float sobelX = 0;
    float sobelY = 0;

    // Loop over sample points
    [unroll] for (int i = 0; i < 9; i++)
    {
    // Sample shadowmap
    float shadowImage = MainLightRealtimeShadow(float4(shadowCoord.xy + sobelSamplePoints[i] * dilation * shadowMap_TexelSize.xy, shadowCoord.zw));

    // Sum the convolution values
    sobelX += shadowImage * sobelXKernel[i];
    sobelY += shadowImage * sobelYKernel[i];
    }

    // Return the magnitude
    return sqrt(sobelX * sobelX + sobelY * sobelY);
    Light light = GetAdditionalLight(j, IN.posWS);
    lightCol += Lambert(light.color * (light.distanceAttenuation * light.shadowAttenuation), light.direction, IN.normalWS);
    }

    float4 frag (Varyings IN) : SV_Target
    {
    float4 shadowCoord = TransformWorldToShadowCoord(IN.posWS);
    float shadowMap = MainLightRealtimeShadow(shadowCoord);

    float NdotL = saturate(dot(_MainLightPosition.xyz, IN.normalWS));

    float combinedShadow = min(NdotL, shadowMap);
    float shadowValue = saturate(step(_ShadowStep, combinedShadow) + _ShadowMin);

    float shadowOutlineMask = ShadowSobelOperator(shadowCoord, _ShadowDilation / pow(2, shadowCoord.w));

    //shadowOutlineMask *= (1 - step(_ShadowStep, shadowMap));
    shadowOutlineMask *= (1 - step(_ShadowStep, shadowMap));
    shadowOutlineMask *= step(_ShadowStep, NdotL);
    float4 shadowCoord = TransformWorldToShadowCoord(IN.posWS);
    float shadowMap = MainLightRealtimeShadow(shadowCoord);

    //float NdotL = saturate(dot(_MainLightPosition.xyz, IN.normalWS));
    float NdotL = saturate(dot(IN.normalWS, _MainLightPosition));

    float combinedShadow = min(NdotL, shadowMap);
    //float shadowValue = saturate(step(_ShadowStep, combinedShadow) + _ShadowStrength);
    float shadowValue = saturate(combinedShadow + _ShadowStrength);

    //float finalShadowValue = shadowValue * (1.0 - _AOStrength) + ao * _AOStrength;
    float finalShadowValue = lerp(shadowValue, ao, _AOStrength);

    float shadowOutlineMask = ShadowSobelOperator(shadowCoord, _ShadowDilation / pow(2, shadowCoord.w));
    shadowOutlineMask *= 1.0 - smoothstep(_ShadowStep - 0.1, _ShadowStep, shadowMap);
    shadowOutlineMask *= step(_ShadowStep, NdotL);

    //float2 normalizedUV = IN.uv * _MainTex_ST.xy + _MainTex_ST.zw;
    float4 texColor = tex2D(_MainTex, IN.uv);
    float3 coloredShadow = _ShadowColour.xyz;
    float3 col = texColor.rgb * finalShadowValue;

    float3 col = texColor.rgb * shadowValue;
    col = lerp(col, _OutlineColor.rgb, saturate(shadowOutlineMask));
    col += coloredShadow * (1.0 - finalShadowValue);
    col = lerp(col, _OutlineColor.rgb, saturate(shadowOutlineMask));

    //float3 finalColor = lightCol * col;
    float3 finalColor = lightCol * col;

    return float4(col, texColor.a);
    }
    ENDHLSL
    return float4(finalColor, 1);
    }
    //[ FRAG ]
    ENDHLSL
    }
    //[ FORWARD LIT ]

    //[ SHADOW CASTER ]
    pass
    {
    Name "ShadowCaster"
    Tags{"LightMode" = "ShadowCaster"}

    Tags { "LightMode" = "ShadowCaster" }
    ZWrite On
    ZTest LEqual
    ColorMask 0

    HLSLPROGRAM

    HLSLPROGRAM
    #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
    #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"

    @@ -157,44 +213,46 @@ Shader "Unlit/SHADOW_OUTLINE"

    struct Attributes
    {
    float4 vertex : POSITION;
    float3 normal : NORMAL;
    float4 vertex : POSITION;
    float3 normal : NORMAL;
    };

    struct Varyings
    {
    float4 posCS : SV_POSITION;
    float4 posCS : SV_POSITION;
    };

    float3 _LightDirection;

    Varyings vert(Attributes IN)
    {
    Varyings OUT = (Varyings)0;
    VertexPositionInputs vertexInput = GetVertexPositionInputs(IN.vertex.xyz);
    float3 posWS = vertexInput.positionWS;
    Varyings vert(Attributes IN)
    {
    Varyings OUT = (Varyings) 0;
    VertexPositionInputs vertexInput = GetVertexPositionInputs(IN.vertex.xyz);
    float3 posWS = vertexInput.positionWS;

    VertexNormalInputs normalInput = GetVertexNormalInputs(IN.normal);
    float3 normalWS = normalInput.normalWS;
    VertexNormalInputs normalInput = GetVertexNormalInputs(IN.normal);
    float3 normalWS = normalInput.normalWS;

    // Shadow biased ClipSpace position
    float4 positionCS = TransformWorldToHClip(ApplyShadowBias(posWS, normalWS, _LightDirection));
    // Shadow biased ClipSpace position
    float4 positionCS = TransformWorldToHClip(ApplyShadowBias(posWS, normalWS, _LightDirection));

    #if UNITY_REVERSED_Z
    positionCS.z = min(positionCS.z, positionCS.w * UNITY_NEAR_CLIP_VALUE);
    #else
    positionCS.z = max(positionCS.z, positionCS.w * UNITY_NEAR_CLIP_VALUE);
    #endif
    #if UNITY_REVERSED_Z
    positionCS.z = min(positionCS.z, positionCS.w * UNITY_NEAR_CLIP_VALUE);
    #else
    positionCS.z = max(positionCS.z, positionCS.w * UNITY_NEAR_CLIP_VALUE);
    #endif

    OUT.posCS = positionCS;
    OUT.posCS = positionCS;

    return OUT;
    }
    float4 frag (Varyings IN) : SV_Target
    return OUT;
    }

    float4 frag(Varyings IN) : SV_Target
    {
    return 0;
    }
    ENDHLSL
    ENDHLSL
    }
    //[ SHADOW CASTER ]
    }
    }
  4. NathoSteveo created this gist Aug 19, 2023.
    200 changes: 200 additions & 0 deletions SHADOW_OUTLINE.shader
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,200 @@
    Shader "Unlit/SHADOW_OUTLINE"
    {
    Properties
    {
    _MainTex ("Texture", 2D) = "white" {}
    //_AOTex ("Ambient Occlusion", 2D) = "white" {}
    _ShadowStep ("Shadow step value", Range(0, 1)) = 0.1
    _ShadowMin ("Minimum shadow value", Range(0, 1)) = 0.2
    _OutlineColor ("Outline color", Color) = (0, 0, 0, 1)
    _ShadowDilation ("Shadow dilation", Range(0, 10)) = 1
    }
    SubShader
    {
    Tags { "RenderType"="Opaque" }
    LOD 200

    Pass
    {
    Name "ForwardLit"
    Tags { "LightMode" = "UniversalForward" }

    HLSLPROGRAM
    #pragma vertex vert
    #pragma fragment frag

    #pragma multi_compile _ _MAIN_LIGHT_SHADOWS
    #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
    #pragma multi_compile _ _SHADOWS_SOFT

    #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
    #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"

    struct Attributes
    {
    float4 vertex : POSITION;
    float3 normal : NORMAL;
    float2 uv : TEXCOORD0;
    };

    struct Varyings
    {
    float4 posCS : SV_POSITION;
    float3 posWS : TEXCOORD0;
    float3 normalWS : TEXCOORD1;
    float2 uv : TEXCOORD2;
    };

    sampler2D _MainTex;
    float4 _MainTex_ST;
    sampler2D _AOTex;

    Varyings vert(Attributes IN)
    {
    Varyings OUT;
    VertexPositionInputs vertexInput = GetVertexPositionInputs(IN.vertex.xyz);
    OUT.posCS = vertexInput.positionCS;
    OUT.posWS = vertexInput.positionWS;

    VertexNormalInputs normalInput = GetVertexNormalInputs(IN.normal);
    OUT.normalWS = normalInput.normalWS;

    OUT.uv = TRANSFORM_TEX(IN.uv, _MainTex);

    return OUT;
    }

    float _ShadowStep, _ShadowMin, _ShadowDilation;
    float3 _OutlineColor;

    // 3x3 sample points
    static float2 sobelSamplePoints[9] = {
    float2(-1, 1), float2(0, 1), float2(1, 1),
    float2(-1, 0), float2(0, 0), float2(1, 0),
    float2(-1, -1), float2(0, -1), float2(1, -1)
    };

    static float sobelXKernel[9] = {
    1, 0, -1,
    2, 0, -2,
    1, 0, -1
    };

    static float sobelYKernel[9] = {
    1, 2, 1,
    0, 0, 0,
    -1, -2, -1
    };

    // Calculate the Sobel operator of the shadowmap
    float ShadowSobelOperator(float4 shadowCoord, float dilation)
    {
    // Get the shadowmap texelsize
    ShadowSamplingData shadowSamplingData = GetMainLightShadowSamplingData();
    float4 shadowMap_TexelSize = shadowSamplingData.shadowmapSize;

    // Initialise results
    float sobelX = 0;
    float sobelY = 0;

    // Loop over sample points
    [unroll] for (int i = 0; i < 9; i++)
    {
    // Sample shadowmap
    float shadowImage = MainLightRealtimeShadow(float4(shadowCoord.xy + sobelSamplePoints[i] * dilation * shadowMap_TexelSize.xy, shadowCoord.zw));

    // Sum the convolution values
    sobelX += shadowImage * sobelXKernel[i];
    sobelY += shadowImage * sobelYKernel[i];
    }

    // Return the magnitude
    return sqrt(sobelX * sobelX + sobelY * sobelY);
    }

    float4 frag (Varyings IN) : SV_Target
    {
    float4 shadowCoord = TransformWorldToShadowCoord(IN.posWS);
    float shadowMap = MainLightRealtimeShadow(shadowCoord);

    float NdotL = saturate(dot(_MainLightPosition.xyz, IN.normalWS));

    float combinedShadow = min(NdotL, shadowMap);
    float shadowValue = saturate(step(_ShadowStep, combinedShadow) + _ShadowMin);

    float shadowOutlineMask = ShadowSobelOperator(shadowCoord, _ShadowDilation / pow(2, shadowCoord.w));

    //shadowOutlineMask *= (1 - step(_ShadowStep, shadowMap));
    shadowOutlineMask *= (1 - step(_ShadowStep, shadowMap));
    shadowOutlineMask *= step(_ShadowStep, NdotL);

    //float2 normalizedUV = IN.uv * _MainTex_ST.xy + _MainTex_ST.zw;
    float4 texColor = tex2D(_MainTex, IN.uv);

    float3 col = texColor.rgb * shadowValue;
    col = lerp(col, _OutlineColor.rgb, saturate(shadowOutlineMask));

    return float4(col, texColor.a);
    }
    ENDHLSL
    }
    pass
    {
    Name "ShadowCaster"
    Tags{"LightMode" = "ShadowCaster"}

    ZWrite On
    ZTest LEqual
    ColorMask 0

    HLSLPROGRAM

    #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
    #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"

    #pragma vertex vert
    #pragma fragment frag

    struct Attributes
    {
    float4 vertex : POSITION;
    float3 normal : NORMAL;
    };

    struct Varyings
    {
    float4 posCS : SV_POSITION;
    };

    float3 _LightDirection;

    Varyings vert(Attributes IN)
    {
    Varyings OUT = (Varyings)0;
    VertexPositionInputs vertexInput = GetVertexPositionInputs(IN.vertex.xyz);
    float3 posWS = vertexInput.positionWS;

    VertexNormalInputs normalInput = GetVertexNormalInputs(IN.normal);
    float3 normalWS = normalInput.normalWS;

    // Shadow biased ClipSpace position
    float4 positionCS = TransformWorldToHClip(ApplyShadowBias(posWS, normalWS, _LightDirection));

    #if UNITY_REVERSED_Z
    positionCS.z = min(positionCS.z, positionCS.w * UNITY_NEAR_CLIP_VALUE);
    #else
    positionCS.z = max(positionCS.z, positionCS.w * UNITY_NEAR_CLIP_VALUE);
    #endif

    OUT.posCS = positionCS;

    return OUT;
    }
    float4 frag (Varyings IN) : SV_Target
    {
    return 0;
    }
    ENDHLSL
    }
    }
    }