Search Unity

Resolved URP Recieve shadow for custom unlit shader.

Discussion in 'Shaders' started by Buttermilch, Mar 21, 2023.

  1. Buttermilch

    Buttermilch

    Joined:
    Nov 23, 2016
    Posts:
    33
    Using Unity 2021.3.6f1 and URP 12.1.7 with a custom unlit shader.

    I'm trying to add shadows to my gpu instanced grass but I can't get it working. I've already figured out how I make the objcets cast shadows but they can't recieve any.
    I've been stuck here for several days now and can't find any solutions (that work for me) on the web or in the Unity documentation.

    I came across posts like these: https://forum.unity.com/threads/wat...al-render-pipeline-order.748142/#post-5518747
    But this does not work either. I don't get any erros, just an transparent object that does not cast shadows.

    Hope someone can help.

    Here is my full shader code so far that is able to cast shadows:

    Code (CSharp):
    1. Shader "Unlit/GrassBladeIndirect"
    2. {
    3.     Properties
    4.     {
    5.         _MainTex ("Main Tex", 2D) = "white" {}
    6.         _RenderTex ("Render Tex", 2D) = "white" {}
    7.         _PrimaryCol ("Primary Color", Color) = (1, 1, 1)
    8.         _SecondaryCol ("Secondary Color", Color) = (1, 0, 1)
    9.         _AOColor ("AO Color", Color) = (1, 0, 1)
    10.         _TipColor ("Tip Color", Color) = (0, 0, 1)
    11.         _Scale ("Scale", Range(0.0, 2.0)) = 0.0
    12.         _MeshDeformationLimit ("Mesh Deformation Limit", Range(0.0, 5.0)) = 0.0
    13.         _WindNoiseScale ("Wind Noise Scale", float) = 0.0
    14.         _WindStrength ("Wind Strength", float) = 1.0
    15.         _WindSpeed ("Wind Speed", Vector) = (0, 0, 0, 0)
    16.     }
    17.     SubShader
    18.     {
    19.         LOD 100
    20.         Cull Off
    21.         ZWrite On
    22.         Name "Grass"
    23.         Tags {
    24.             "RenderType"="Opaque"
    25.             "RenderPipeline"="UniversalPipeline"
    26.             "LightMode"="UniversalForwardOnly"
    27.         }
    28.  
    29.         Pass
    30.         {
    31.  
    32.             Name "ForwardLit"
    33.             Tags { "LightMode" = "UniversalForwardOnly" }
    34.  
    35.             CGPROGRAM
    36.             #pragma vertex vert
    37.             #pragma fragment frag
    38.             // make fog work
    39.             #pragma multi_compile_fog
    40.             #pragma multi_compile_instancing
    41.             #pragma target 4.5
    42.  
    43.             #pragma multi_compile _ _MAIN_LIGHT_SHADOWS
    44.             #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
    45.             #pragma multi_compile _ _SHADOWS_SOFT
    46.             #include "UnityCG.cginc"
    47.  
    48.             struct appdata
    49.             {
    50.                 float4 vertex : POSITION;
    51.                 float2 uv : TEXCOORD0;
    52.             };
    53.  
    54.             struct v2f
    55.             {
    56.                 float2 uv : TEXCOORD0;
    57.                 UNITY_FOG_COORDS(1)
    58.                 float4 vertex : SV_POSITION;
    59.             };
    60.  
    61.              //TODO: move into separate hlsl file, generated by shadergraph
    62.             inline float Unity_SimpleNoise_RandomValue_float (float2 uv)
    63.             {
    64.                   return frac(sin(dot(uv, float2(12.9898, 78.233)))*43758.5453);
    65.             }
    66.  
    67.             //TODO: move into separate hlsl file, generated by shadergraph
    68.             inline float Unity_SimpleNnoise_Interpolate_float (float a, float b, float t)
    69.             {
    70.                  return (1.0-t)*a + (t*b);
    71.             }
    72.          
    73.              //TODO: move into separate hlsl file, generated by shadergraph
    74.             inline float Unity_SimpleNoise_ValueNoise_float (float2 uv)
    75.             {
    76.                 float2 i = floor(uv);
    77.                 float2 f = frac(uv);
    78.                 f = f * f * (3.0 - 2.0 * f);
    79.  
    80.                 uv = abs(frac(uv) - 0.5);
    81.                 float2 c0 = i + float2(0.0, 0.0);
    82.                 float2 c1 = i + float2(1.0, 0.0);
    83.                 float2 c2 = i + float2(0.0, 1.0);
    84.                 float2 c3 = i + float2(1.0, 1.0);
    85.                 float r0 = Unity_SimpleNoise_RandomValue_float(c0);
    86.                 float r1 = Unity_SimpleNoise_RandomValue_float(c1);
    87.                 float r2 = Unity_SimpleNoise_RandomValue_float(c2);
    88.                 float r3 = Unity_SimpleNoise_RandomValue_float(c3);
    89.  
    90.                 float bottomOfGrid = Unity_SimpleNnoise_Interpolate_float(r0, r1, f.x);
    91.                 float topOfGrid = Unity_SimpleNnoise_Interpolate_float(r2, r3, f.x);
    92.                 float t = Unity_SimpleNnoise_Interpolate_float(bottomOfGrid, topOfGrid, f.y);
    93.                 return t;
    94.             }
    95.              //TODO: move into separate hlsl file, generated by shadergraph
    96.             void Unity_SimpleNoise_float(float2 UV, float Scale, out float Out) {
    97.                 float t = 0.0;
    98.  
    99.                 float freq = pow(2.0, float(0));
    100.                 float amp = pow(0.5, float(3-0));
    101.                 t += Unity_SimpleNoise_ValueNoise_float(float2(UV.x*Scale/freq, UV.y*Scale/freq))*amp;
    102.  
    103.                 freq = pow(2.0, float(1));
    104.                 amp = pow(0.5, float(3-1));
    105.                 t += Unity_SimpleNoise_ValueNoise_float(float2(UV.x*Scale/freq, UV.y*Scale/freq))*amp;
    106.  
    107.                 freq = pow(2.0, float(2));
    108.                 amp = pow(0.5, float(3-2));
    109.                 t += Unity_SimpleNoise_ValueNoise_float(float2(UV.x*Scale/freq, UV.y*Scale/freq))*amp;
    110.  
    111.                 Out = t;
    112.             }
    113.  
    114.             StructuredBuffer<float4x4> trsBuffer;
    115.             sampler2D _MainTex;
    116.             sampler2D _RenderTex;
    117.             float4 _MainTex_ST;
    118.             float4 _RenderTex_ST;
    119.             float4 _PrimaryCol, _SecondaryCol, _AOColor, _TipColor;
    120.             float _Scale;
    121.             float4 _LightDir;
    122.             float _MeshDeformationLimit;
    123.             float4 _WindSpeed;
    124.             float _WindStrength;
    125.             float _WindNoiseScale;
    126.  
    127.             v2f vert (appdata v, uint instanceID : SV_InstanceID)
    128.             {
    129.  
    130.                  v2f o;
    131.  
    132.                 //applying transformation matrix
    133.                 float3 positionWorldSpace = mul(trsBuffer[instanceID], float4(v.vertex.xyz, 1));
    134.  
    135.                 //move world UVs by time
    136.                 float4 worldPos = float4(positionWorldSpace, 1);
    137.                 float2 worldUV = worldPos.xz + _WindSpeed * _Time.y;
    138.  
    139.                 //creating noise from world UVs
    140.                 float noise = 0;
    141.                 Unity_SimpleNoise_float(worldUV, _WindNoiseScale, noise);
    142.                 noise = pow(noise, 2);
    143.  
    144.                 //to keep bottom part of mesh at its position
    145.                 o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    146.                 float smoothDeformation = smoothstep(0, _MeshDeformationLimit, o.uv.y);
    147.                 float distortion = smoothDeformation * noise;
    148.  
    149.                 //apply distortion
    150.                 positionWorldSpace.x += distortion * _WindStrength;
    151.                 o.vertex = mul(UNITY_MATRIX_VP, float4(positionWorldSpace, 1));
    152.  
    153.                 UNITY_TRANSFER_FOG(o,o.vertex);
    154.  
    155.  
    156.                 return o;
    157.             }
    158.  
    159.             fixed4 frag (v2f i) : SV_Target
    160.             {
    161.              
    162.                 float4 col = lerp(_PrimaryCol, _SecondaryCol, i.uv.y);
    163.  
    164.                 //from https://github.com/GarrettGunnell/Grass/blob/main/Assets/Shaders/ModelGrass.shader
    165.                 float light = clamp(dot(_LightDir, normalize(float3(0, 1, 0))), 0 , 1);
    166.                 float4 ao = lerp(_AOColor, 1.0f, i.uv.y);
    167.                 float4 tip = lerp(0.0f, _TipColor, i.uv.y * i.uv.y * (1.0f + _Scale));
    168.                 float4 grassColor = (col + tip) * light * ao;
    169.  
    170.  
    171.                 // apply fog
    172.                 UNITY_APPLY_FOG(i.fogCoord, col);
    173.                 return grassColor;
    174.             }
    175.             ENDCG
    176.         }
    177.      
    178.         Pass {
    179.             Name "ShadowCaster"
    180.             Tags { "LightMode" = "ShadowCaster" }
    181.             ZWrite On
    182.             ColorMask 0
    183.             LOD 100
    184.             Cull Off
    185.  
    186.             CGPROGRAM
    187.             #pragma vertex vert
    188.             #pragma fragment frag
    189.             // make fog work
    190.             #pragma multi_compile_fog
    191.             #pragma multi_compile_instancing
    192.             #pragma target 4.5
    193.             #include "UnityCG.cginc"
    194.  
    195.             struct appdata
    196.             {
    197.                 float4 vertex : POSITION;
    198.                 float2 uv : TEXCOORD0;
    199.             };
    200.  
    201.             struct v2f
    202.             {
    203.                 float2 uv : TEXCOORD0;
    204.                 UNITY_FOG_COORDS(1)
    205.                 float4 vertex : SV_POSITION;
    206.             };
    207.  
    208.             //TODO: move into separate hlsl file, generated by shadergraph
    209.             inline float Unity_SimpleNoise_RandomValue_float (float2 uv)
    210.             {
    211.                   return frac(sin(dot(uv, float2(12.9898, 78.233)))*43758.5453);
    212.             }
    213.          
    214.              //TODO: move into separate hlsl file, generated by shadergraph
    215.             inline float Unity_SimpleNnoise_Interpolate_float (float a, float b, float t)
    216.             {
    217.                  return (1.0-t)*a + (t*b);
    218.             }
    219.  
    220.              //TODO: move into separate hlsl file, generated by shadergraph
    221.             inline float Unity_SimpleNoise_ValueNoise_float (float2 uv)
    222.             {
    223.                 float2 i = floor(uv);
    224.                 float2 f = frac(uv);
    225.                 f = f * f * (3.0 - 2.0 * f);
    226.  
    227.                 uv = abs(frac(uv) - 0.5);
    228.                 float2 c0 = i + float2(0.0, 0.0);
    229.                 float2 c1 = i + float2(1.0, 0.0);
    230.                 float2 c2 = i + float2(0.0, 1.0);
    231.                 float2 c3 = i + float2(1.0, 1.0);
    232.                 float r0 = Unity_SimpleNoise_RandomValue_float(c0);
    233.                 float r1 = Unity_SimpleNoise_RandomValue_float(c1);
    234.                 float r2 = Unity_SimpleNoise_RandomValue_float(c2);
    235.                 float r3 = Unity_SimpleNoise_RandomValue_float(c3);
    236.  
    237.                 float bottomOfGrid = Unity_SimpleNnoise_Interpolate_float(r0, r1, f.x);
    238.                 float topOfGrid = Unity_SimpleNnoise_Interpolate_float(r2, r3, f.x);
    239.                 float t = Unity_SimpleNnoise_Interpolate_float(bottomOfGrid, topOfGrid, f.y);
    240.                 return t;
    241.             }
    242.              //TODO: move into separate hlsl file, generated by shadergraph
    243.             void Unity_SimpleNoise_float(float2 UV, float Scale, out float Out) {
    244.                 float t = 0.0;
    245.  
    246.                 float freq = pow(2.0, float(0));
    247.                 float amp = pow(0.5, float(3-0));
    248.                 t += Unity_SimpleNoise_ValueNoise_float(float2(UV.x*Scale/freq, UV.y*Scale/freq))*amp;
    249.  
    250.                 freq = pow(2.0, float(1));
    251.                 amp = pow(0.5, float(3-1));
    252.                 t += Unity_SimpleNoise_ValueNoise_float(float2(UV.x*Scale/freq, UV.y*Scale/freq))*amp;
    253.  
    254.                 freq = pow(2.0, float(2));
    255.                 amp = pow(0.5, float(3-2));
    256.                 t += Unity_SimpleNoise_ValueNoise_float(float2(UV.x*Scale/freq, UV.y*Scale/freq))*amp;
    257.  
    258.                 Out = t;
    259.             }
    260.  
    261.             StructuredBuffer<float4x4> trsBuffer;
    262.             sampler2D _MainTex;
    263.             float4 _MainTex_ST;
    264.             float _MeshDeformationLimit;
    265.             float4 _WindSpeed;
    266.             float _WindStrength;
    267.             float _WindNoiseScale;
    268.  
    269.             v2f vert (appdata v, uint instanceID : SV_InstanceID)
    270.             {
    271.                 v2f o;
    272.          
    273.                 //applying transformation matrix
    274.                 float3 positionWorldSpace = mul(trsBuffer[instanceID], float4(v.vertex.xyz, 1));
    275.  
    276.                 //move world UVs by time
    277.                 float4 worldPos = float4(positionWorldSpace, 1);
    278.                 float2 worldUV = worldPos.xz + _WindSpeed * _Time.y;
    279.  
    280.                 //creating noise from world UVs
    281.                 float noise = 0;
    282.                 Unity_SimpleNoise_float(worldUV, _WindNoiseScale, noise);
    283.                 noise = pow(noise, 2);
    284.  
    285.                 //to keep bottom part of mesh at its position
    286.                 o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    287.                 float smoothDeformation = smoothstep(0, _MeshDeformationLimit, o.uv.y);
    288.                 float distortion = smoothDeformation * noise;
    289.  
    290.                 //apply distortion
    291.                 positionWorldSpace.x += distortion * _WindStrength;
    292.                 o.vertex = mul(UNITY_MATRIX_VP, float4(positionWorldSpace, 1));
    293.  
    294.                 UNITY_TRANSFER_FOG(o,o.vertex);
    295.                 return o;
    296.             }
    297.  
    298.            fixed4 frag (v2f i) : SV_Target
    299.            {
    300.                 SHADOW_CASTER_FRAGMENT(i);
    301.            }
    302.            ENDCG
    303.        }
    304.     }
    305.  
    306.     Fallback "VertexLix"
    307. }
    upload_2023-3-21_18-35-21.png upload_2023-3-21_18-35-21.png
     
  2. Buttermilch

    Buttermilch

    Joined:
    Nov 23, 2016
    Posts:
    33
    Small update:
    I've researched again on this topic and found out I need the
    shadowCoords 
    for the
    shadowMap
    .

    By changing
    CGPROGRAM 
    to
    HLSLPROGRAM
    , I can include the following files:

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

    This let's me now compute the shadowcoord like this in the vertex shader:

     VertexPositionInputs vertexInput = GetVertexPositionInputs(v.vertex.xyz);
    o.shadowCoord = GetShadowCoord(vertexInput);


    The fragment shader then can retrieve the shadow data with:
    Light mainLight = GetMainLight(i.shadowCoord);

    And use
     mainLight.distanceAttenuation
    and
    mainLight.shadowAttenuation


    BUT this does not work. Distance and shadow atten are both 0.
    I've seen other approaches for the to get the shadowCoord with:
    o.shadowCoord = ComputeScreenPos(v.vertex)

    But that would only work for screen space shadows(??).

    Anyways, when I use the
    ComputeScreenPos
    approach, I can at least see something changing on the material.. but it looks like the shadow coords are wrong.

    I'm lost.

    Here's the shader pass I'm currently using:
    Code (CSharp):
    1. Pass
    2.         {
    3.  
    4.             Name "ForwardLit"
    5.             Tags { "LightMode" = "UniversalForwardOnly" }
    6.  
    7.             HLSLPROGRAM
    8.             #pragma vertex vert
    9.             #pragma fragment frag
    10.             // make fog work
    11.             #pragma multi_compile_fog
    12.             #pragma multi_compile_instancing
    13.             #pragma target 4.5
    14.  
    15.             #pragma multi_compile _ _MAIN_LIGHT_SHADOWS
    16.             #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
    17.             #pragma multi_compile _ _SHADOWS_SOFT
    18.             #pragma shader_feature _ALPHATEST_ON
    19.  
    20.             #pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
    21.             #pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS
    22.             #pragma multi_compile _ _MIXED_LIGHTING_SUBTRACTIVE
    23.             #include "noise.hlsl"
    24.             #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
    25.             #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
    26.             #include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
    27.  
    28.             struct appdata
    29.             {
    30.                 float4 vertex : POSITION;
    31.                 float2 uv : TEXCOORD0;
    32.                 float3 normal: NORMAL;
    33.             };
    34.  
    35.             struct v2f
    36.             {
    37.                 float2 uv : TEXCOORD0;
    38.                 float4 vertex : SV_POSITION;
    39.                 float4 shadowCoord: TEXCOORD3;
    40.                 float3 normalWS : TEXCOORD1;
    41.             };
    42.  
    43.             StructuredBuffer<float4x4> trsBuffer;
    44.             sampler2D _MainTex;
    45.             sampler2D _RenderTex;
    46.             float4 _MainTex_ST;
    47.             float4 _RenderTex_ST;
    48.             float4 _PrimaryCol, _SecondaryCol, _AOColor, _TipColor;
    49.             float _Scale;
    50.             float4 _LightDir;
    51.             float _MeshDeformationLimit;
    52.             float4 _WindSpeed;
    53.             float _WindStrength;
    54.             float _WindNoiseScale;
    55.  
    56.             v2f vert (appdata v, uint instanceID : SV_InstanceID)
    57.             {
    58.                 v2f o;
    59.  
    60.                 //applying transformation matrix
    61.                 float3 positionWorldSpace = mul(trsBuffer[instanceID], float4(v.vertex.xyz, 1));
    62.  
    63.                 //move world UVs by time
    64.                 float4 worldPos = float4(positionWorldSpace, 1);
    65.                 float2 worldUV = worldPos.xz + _WindSpeed * _Time.y;
    66.  
    67.                 //creating noise from world UVs
    68.                 float noise = 0;
    69.                 Unity_SimpleNoise_float(worldUV, _WindNoiseScale, noise);
    70.                 noise = pow(noise, 2);
    71.  
    72.                 //to keep bottom part of mesh at its position
    73.                 o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    74.                 float smoothDeformation = smoothstep(0, _MeshDeformationLimit, o.uv.y);
    75.                 float distortion = smoothDeformation * noise;
    76.  
    77.                 //apply distortion
    78.                 positionWorldSpace.x += distortion * _WindStrength;
    79.                 o.vertex = mul(UNITY_MATRIX_VP, float4(positionWorldSpace, 1));
    80.  
    81.  
    82.                 VertexPositionInputs vertexInput = GetVertexPositionInputs(v.vertex.xyz);
    83.                 o.shadowCoord = GetShadowCoord(vertexInput);
    84.  
    85.                 VertexNormalInputs normal = GetVertexNormalInputs(v.normal);
    86.                 o.normalWS = normal.normalWS;
    87.                 o.shadowCoord = ComputeScreenPos(v.vertex);
    88.                
    89.                 return o;
    90.             }
    91.  
    92.             float4 frag (v2f i) : SV_Target
    93.             {
    94.                 float4 col = lerp(_PrimaryCol, _SecondaryCol, i.uv.y);
    95.  
    96.                 //from https://github.com/GarrettGunnell/Grass/blob/main/Assets/Shaders/ModelGrass.shader
    97.                 float light = clamp(dot(_LightDir, normalize(float3(0, 1, 0))), 0 , 1);
    98.                 float4 ao = lerp(_AOColor, 1.0f, i.uv.y);
    99.                 float4 tip = lerp(0.0f, _TipColor, i.uv.y * i.uv.y * (1.0f + _Scale));
    100.                 float4 grassColor = (col + tip) * light * ao;
    101.  
    102.                  Light mainLight = GetMainLight(i.shadowCoord);
    103.                  float strength = dot(mainLight.direction, i.normalWS);
    104.                  float4 lightColor = float4(mainLight.color, 1)*(mainLight.distanceAttenuation * mainLight.shadowAttenuation);
    105.                // half receiveshadow = MainLightRealtimeShadow(i.shadowCoord);
    106.  
    107.  
    108.                 return grassColor * lightColor * strength;
    109.             }
    110.             ENDHLSL
    111.         }


    upload_2023-3-24_17-45-15.png upload_2023-3-24_17-45-30.png
     
  3. Buttermilch

    Buttermilch

    Joined:
    Nov 23, 2016
    Posts:
    33
    Update: I got it working!
    In my previous answer, I've had calculated the shadow coords wrong. So I digged trough Unity's shaders again and found this line which gets called in the vertex shader:
    inputData.shadowCoord = TransformWorldToShadowCoord(inputData.positionWS);

    Then in the fragment shader I can simply do:
     Light mainLight = GetMainLight(i.shadowCoord);

    To access the mainLight.distanceAttenuation and mainLight.shadowAttenuation

    This is also works:
    half s = MainLightRealtimeShadow(i.shadowCoord);
    but I don't know what's the difference because it gives me the same results.

    Also weird thing I noticed is that it still works without an extra depth pass.

    Anyways here is my full shader code for my gpu instanced grass that can cast and recieve shadows:
    (still in the stage from my experiments, so not really refactored)
    Code (CSharp):
    1. Shader "Unlit/GrassBladeIndirect"
    2. {
    3.     Properties
    4.     {
    5.         _MainTex ("Main Tex", 2D) = "white" {}
    6.         _RenderTex ("Render Tex", 2D) = "white" {}
    7.         _PrimaryCol ("Primary Color", Color) = (1, 1, 1)
    8.         _SecondaryCol ("Secondary Color", Color) = (1, 0, 1)
    9.         _AOColor ("AO Color", Color) = (1, 0, 1)
    10.         _TipColor ("Tip Color", Color) = (0, 0, 1)
    11.         _Scale ("Scale", Range(0.0, 2.0)) = 0.0
    12.         _MeshDeformationLimit ("Mesh Deformation Limit", Range(0.0, 5.0)) = 0.0
    13.         _WindNoiseScale ("Wind Noise Scale", float) = 0.0
    14.         _WindStrength ("Wind Strength", float) = 1.0
    15.         _WindSpeed ("Wind Speed", Vector) = (0, 0, 0, 0)
    16.     }
    17.     SubShader
    18.     {
    19.         LOD 100
    20.         Cull Off
    21.         ZWrite On
    22.         Name "Grass"
    23.         Tags {
    24.             "RenderType"="Opaque"
    25.             "RenderPipeline"="UniversalPipeline"
    26.             "LightMode"="UniversalForwardOnly"
    27.             "Queue"="Geometry"
    28.         }
    29.  
    30.         Pass
    31.         {
    32.  
    33.             Name "ForwardLit"
    34.             Tags { "LightMode" = "UniversalForwardOnly" }
    35.  
    36.             HLSLPROGRAM
    37.  
    38.             #pragma vertex vert
    39.             #pragma fragment frag
    40.  
    41.             #pragma prefer_hlslcc gles
    42.             #pragma exclude_renderers d3d11_9x
    43.  
    44.             #pragma multi_compile_fog
    45.             #pragma multi_compile_instancing
    46.             #pragma target 4.5
    47.  
    48.             #pragma multi_compile _ _MAIN_LIGHT_SHADOWS
    49.             #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
    50.             #pragma multi_compile _ _SHADOWS_SOFT
    51.             #pragma shader_feature _ALPHATEST_ON
    52.  
    53.             #pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
    54.             #pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS
    55.             #pragma multi_compile _ _MIXED_LIGHTING_SUBTRACTIVE
    56.             #include "noise.hlsl"
    57.             #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
    58.             #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
    59.  
    60.             struct VertexInput
    61.             {
    62.                 float4 vertex : POSITION;
    63.                 float2 uv : TEXCOORD0;
    64.                 float3 normal: NORMAL;
    65.             };
    66.  
    67.             struct VertexOutput
    68.             {
    69.                 float4 vertex : SV_POSITION;
    70.                 float2 uv : TEXCOORD0;
    71.                 float3 normal : NORMAL;
    72.                 float4 shadowCoord: TEXCOORD2;
    73.                 float4 interp8 : INTERP8;
    74.             };
    75.  
    76.             StructuredBuffer<float4x4> trsBuffer;
    77.             sampler2D _MainTex;
    78.             sampler2D _RenderTex;
    79.             float4 _MainTex_ST;
    80.             float4 _RenderTex_ST;
    81.             float4 _PrimaryCol, _SecondaryCol, _AOColor, _TipColor;
    82.             float _Scale;
    83.             float4 _LightDir;
    84.             float _MeshDeformationLimit;
    85.             float4 _WindSpeed;
    86.             float _WindStrength;
    87.             float _WindNoiseScale;
    88.  
    89.             VertexOutput vert (VertexInput v, uint instanceID : SV_InstanceID)
    90.             {
    91.                 VertexOutput o;
    92.  
    93.  
    94.                 //applying transformation matrix
    95.                 float3 positionWorldSpace = mul(trsBuffer[instanceID], float4(v.vertex.xyz, 1));
    96.  
    97.                 //move world UVs by time
    98.                 float4 worldPos = float4(positionWorldSpace, 1);
    99.                 float2 worldUV = worldPos.xz + _WindSpeed * _Time.y;
    100.  
    101.                 //creating noise from world UVs
    102.                 float noise = 0;
    103.                 Unity_SimpleNoise_float(worldUV, _WindNoiseScale, noise);
    104.                 noise = pow(noise, 2);
    105.  
    106.                 //to keep bottom part of mesh at its position
    107.                 o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    108.                 float smoothDeformation = smoothstep(0, _MeshDeformationLimit, o.uv.y);
    109.                 float distortion = smoothDeformation * noise;
    110.  
    111.                 //apply distortion
    112.                 positionWorldSpace.x += distortion * _WindStrength;
    113.                 o.vertex = mul(UNITY_MATRIX_VP, float4(positionWorldSpace, 1));
    114.  
    115.                 VertexPositionInputs vertexInput = GetVertexPositionInputs(v.vertex.xyz);
    116.                 o.shadowCoord = TransformWorldToShadowCoord(positionWorldSpace);
    117.  
    118.                 VertexNormalInputs normal = GetVertexNormalInputs(v.normal);
    119.                 o.normal = normalize(mul(v.normal, (float3x3)UNITY_MATRIX_I_M));
    120.                
    121.                 return o;
    122.             }
    123.  
    124.             float4 frag (VertexOutput i) : SV_Target
    125.             {
    126.    
    127.                 float4 col = lerp(_PrimaryCol, _SecondaryCol, i.uv.y);
    128.  
    129.                 //from https://github.com/GarrettGunnell/Grass/blob/main/Assets/Shaders/ModelGrass.shader
    130.                 float light = clamp(dot(_LightDir, normalize(float3(0, 1, 0))), 0 , 1);
    131.                 float4 ao = lerp(_AOColor, 1.0f, i.uv.y);
    132.                 float4 tip = lerp(0.0f, _TipColor, i.uv.y * i.uv.y * (1.0f + _Scale));
    133.                 float4 grassColor = (col + tip) * light * ao;
    134.  
    135.                  Light mainLight = GetMainLight(i.shadowCoord);
    136.                  float strength = dot(mainLight.direction, i.normal);
    137.                  float4 lightColor = float4(mainLight.color, 1)*(mainLight.distanceAttenuation * mainLight.shadowAttenuation);
    138.              
    139.                   half receiveshadow = MainLightRealtimeShadow(i.shadowCoord);
    140.  
    141.                 return grassColor * receiveshadow;
    142.             }
    143.             ENDHLSL
    144.         }
    145.  
    146. //Shadow caster pass    
    147.         Pass {
    148.             Name "ShadowCaster"
    149.             Tags { "LightMode" = "ShadowCaster" }
    150.             ZWrite On
    151.             ColorMask 0
    152.             LOD 100
    153.             Cull Off
    154.  
    155.             HLSLPROGRAM
    156.             #pragma vertex vert
    157.             #pragma fragment frag
    158.             // make fog work
    159.             #pragma multi_compile_fog
    160.             #pragma multi_compile_instancing
    161.             #pragma target 4.5
    162.  
    163.             #include "UnityCG.cginc"
    164.             #include "noise.hlsl"
    165.  
    166.             struct VertexInput
    167.             {
    168.                 float4 vertex : POSITION;
    169.                 float2 uv : TEXCOORD0;
    170.             };
    171.  
    172.             struct VertexOutput
    173.             {
    174.                 float2 uv : TEXCOORD0;
    175.                 UNITY_FOG_COORDS(1)
    176.                 float4 vertex : SV_POSITION;
    177.             };
    178.  
    179.             StructuredBuffer<float4x4> trsBuffer;
    180.             sampler2D _MainTex;
    181.             float4 _MainTex_ST;
    182.             float _MeshDeformationLimit;
    183.             float4 _WindSpeed;
    184.             float _WindStrength;
    185.             float _WindNoiseScale;
    186.  
    187.             VertexOutput vert (VertexInput v, uint instanceID : SV_InstanceID)
    188.             {
    189.                 VertexOutput o;
    190.          
    191.                 //applying transformation matrix
    192.                 float3 positionWorldSpace = mul(trsBuffer[instanceID], float4(v.vertex.xyz, 1));
    193.  
    194.                 //move world UVs by time
    195.                 float4 worldPos = float4(positionWorldSpace, 1);
    196.                 float2 worldUV = worldPos.xz + _WindSpeed * _Time.y;
    197.  
    198.                 //creating noise from world UVs
    199.                 float noise = 0;
    200.                 Unity_SimpleNoise_float(worldUV, _WindNoiseScale, noise);
    201.                 noise = pow(noise, 2);
    202.  
    203.                 //to keep bottom part of mesh at its position
    204.                 o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    205.                 float smoothDeformation = smoothstep(0, _MeshDeformationLimit, o.uv.y);
    206.                 float distortion = smoothDeformation * noise;
    207.  
    208.                 //apply distortion
    209.                 positionWorldSpace.x += distortion * _WindStrength;
    210.                 o.vertex = mul(UNITY_MATRIX_VP, float4(positionWorldSpace, 1));
    211.  
    212.                 return o;
    213.             }
    214.  
    215.            fixed4 frag (VertexOutput i) : SV_Target
    216.            {
    217.                 SHADOW_CASTER_FRAGMENT(i);
    218.            }
    219.            ENDHLSL
    220.        }
    221.     }
    222. }
    Here's noise.hlsl:
    Code (CSharp):
    1. #ifndef NOISE
    2. #define NOISE
    3. // generated by shadergraph
    4. inline float Unity_SimpleNoise_RandomValue_float(float2 uv)
    5. {
    6.     return frac(sin(dot(uv, float2(12.9898, 78.233))) * 43758.5453);
    7. }
    8.  
    9. // generated by shadergraph
    10. inline float Unity_SimpleNnoise_Interpolate_float(float a, float b, float t)
    11. {
    12.     return (1.0 - t) * a + (t * b);
    13. }
    14.  
    15. // generated by shadergraph
    16. inline float Unity_SimpleNoise_ValueNoise_float(float2 uv)
    17. {
    18.     float2 i = floor(uv);
    19.     float2 f = frac(uv);
    20.     f = f * f * (3.0 - 2.0 * f);
    21.  
    22.     uv = abs(frac(uv) - 0.5);
    23.     float2 c0 = i + float2(0.0, 0.0);
    24.     float2 c1 = i + float2(1.0, 0.0);
    25.     float2 c2 = i + float2(0.0, 1.0);
    26.     float2 c3 = i + float2(1.0, 1.0);
    27.     float r0 = Unity_SimpleNoise_RandomValue_float(c0);
    28.     float r1 = Unity_SimpleNoise_RandomValue_float(c1);
    29.     float r2 = Unity_SimpleNoise_RandomValue_float(c2);
    30.     float r3 = Unity_SimpleNoise_RandomValue_float(c3);
    31.  
    32.     float bottomOfGrid = Unity_SimpleNnoise_Interpolate_float(r0, r1, f.x);
    33.     float topOfGrid = Unity_SimpleNnoise_Interpolate_float(r2, r3, f.x);
    34.     float t = Unity_SimpleNnoise_Interpolate_float(bottomOfGrid, topOfGrid, f.y);
    35.     return t;
    36. }
    37.  
    38. // generated by shadergraph
    39. void Unity_SimpleNoise_float(float2 UV, float Scale, out float Out)
    40. {
    41.     float t = 0.0;
    42.  
    43.     float freq = pow(2.0, float(0));
    44.     float amp = pow(0.5, float(3 - 0));
    45.     t += Unity_SimpleNoise_ValueNoise_float(float2(UV.x * Scale / freq, UV.y * Scale / freq)) * amp;
    46.  
    47.     freq = pow(2.0, float(1));
    48.     amp = pow(0.5, float(3 - 1));
    49.     t += Unity_SimpleNoise_ValueNoise_float(float2(UV.x * Scale / freq, UV.y * Scale / freq)) * amp;
    50.  
    51.     freq = pow(2.0, float(2));
    52.     amp = pow(0.5, float(3 - 2));
    53.     t += Unity_SimpleNoise_ValueNoise_float(float2(UV.x * Scale / freq, UV.y * Scale / freq)) * amp;
    54.  
    55.     Out = t;
    56. }
    57. #endif
    upload_2023-3-25_9-10-37.png
     
    NathBar and Thomas-Mountainborn like this.
  4. Thundernerd

    Thundernerd

    Joined:
    Jan 24, 2014
    Posts:
    20
    Could you share your shader?
    I'm looking for an unlit shader that works with shadows but I'm struggling quite a bit. I've stumbled upon the GetShadowCoord as well but get all kinds of errors when trying to use this :(
     
  5. Buttermilch

    Buttermilch

    Joined:
    Nov 23, 2016
    Posts:
    33
    The code is in my last reply but here's a slightly refactored version (used for grass instancing)
     
  6. Thundernerd

    Thundernerd

    Joined:
    Jan 24, 2014
    Posts:
    20