Search Unity

Question Can't get point/spot shadows working on grass shader

Discussion in 'Shaders' started by MisterNebula, Jun 20, 2022.

  1. MisterNebula

    MisterNebula

    Joined:
    Jun 23, 2020
    Posts:
    2
    Hey,

    I'm working on a grass shader that creates the grass with a geometry shader. I've got directional lighting and shadows working, alongside ambient lighting and light attenuation for spot/point lights.

    upload_2022-6-20_16-3-13.png

    However, I can't figure out how to get shadows cast by spot/point lights to render on the grass.

    upload_2022-6-20_16-2-36.png

    Here's the full shader code, I would be very grateful for any help.

    Code (CSharp):
    1. Shader "GW/Foliage/Grass"
    2. {
    3.     Properties
    4.     {
    5.         _BottomColor("Bottom Color", Color) = (0,1,0,1)
    6.         _TopColor("Top Color", Color) = (1,1,0,1)
    7.         _GrassHeight("Grass Height", Float) = 1
    8.         _GrassWidth("Grass Width", Float) = 0.06
    9.         _RandomHeight("Grass Height Randomness", Float) = 0.25
    10.         _WindSpeed("Wind Speed", Float) = 100
    11.         _WindStrength("Wind Strength", Float) = 0.05
    12.         _Rad("Blade Radius", Range(0,1)) = 0.6
    13.         _BladeForward("Blade Forward Amount", Float) = 0.38
    14.         _BladeCurve("Blade Curvature Amount", Range(1, 4)) = 2
    15.         _AmbientStrength("Ambient Strength",  Range(0,1)) = 0.5
    16.         _MinDist("Min Distance", Float) = 40
    17.         _MaxDist("Max Distance", Float) = 60
    18.     }
    19.  
    20.     CGINCLUDE
    21.  
    22.     #include "UnityCG.cginc"
    23.     #include "Lighting.cginc"
    24.     #include "AutoLight.cginc"
    25.     #include "UnityLightingCommon.cginc"
    26.     #pragma multi_compile_fwdbase_fullforwardshadows
    27.     #pragma multi_compile_fog
    28.     #define GrassSegments 5
    29.     #define GrassBlades 4
    30.  
    31.     struct v2g
    32.     {
    33.         float4 pos : SV_POSITION;
    34.         float3 norm : NORMAL;
    35.         float2 uv : TEXCOORD0;
    36.     };
    37.  
    38.     struct g2f
    39.     {
    40.         float4 pos : SV_POSITION;
    41.         float3 norm : NORMAL;
    42.         float2 uv : TEXCOORD0;
    43.         float3 worldPos : TEXCOORD3;
    44.         LIGHTING_COORDS(5, 6)
    45.         UNITY_FOG_COORDS(4)
    46.     };
    47.  
    48.     half _GrassHeight;
    49.     half _GrassWidth;
    50.     half _WindSpeed;
    51.     float _WindStrength;
    52.     half _Radius, _Strength;
    53.     float _Rad;
    54.  
    55.     float _RandomHeight;
    56.     float _BladeForward;
    57.     float _BladeCurve;
    58.  
    59.     float _MinDist, _MaxDist;
    60.  
    61.     uniform float3 _PositionMoving;
    62.  
    63.     v2g vert(appdata_full input)
    64.     {
    65.         float3 v0 = input.vertex.xyz;
    66.  
    67.         v2g output;
    68.         output.pos = input.vertex;
    69.         output.norm = input.normal;
    70.         output.uv = input.texcoord;
    71.         return output;
    72.     }
    73.  
    74.     float rand(float3 co)
    75.     {
    76.         return frac(sin(dot(co.xyz, float3(12.9898, 78.233, 53.539))) * 43758.5453);
    77.     }
    78.  
    79.     // https://gist.github.com/keijiro/ee439d5e7388f3aafc5296005c8c3f33
    80.     float3x3 AngleAxis3x3(float angle, float3 axis)
    81.     {
    82.         float c, s;
    83.         sincos(angle, s, c);
    84.  
    85.         float t = 1 - c;
    86.         float x = axis.x;
    87.         float y = axis.y;
    88.         float z = axis.z;
    89.  
    90.         return float3x3(
    91.             t * x * x + c, t * x * y - s * z, t * x * z + s * y,
    92.             t * x * y + s * z, t * y * y + c, t * y * z - s * x,
    93.             t * x * z - s * y, t * y * z + s * x, t * z * z + c
    94.             );
    95.     }
    96.  
    97.     struct unityTransferVertexToFragmentHack
    98.     {
    99.         float3 vertex : POSITION;
    100.     };
    101.  
    102.     g2f GrassVertex(float3 vertexPos, float width, float height, float offset, float curve, float2 uv, float3x3 rotation, float3 faceNormal, float3 worldPos) {
    103.         g2f OUT;
    104.         OUT.pos = UnityObjectToClipPos(vertexPos + mul(rotation, float3(width, height, curve) + float3(0, 0, offset)));
    105.         OUT.norm = faceNormal;
    106.         OUT.uv = uv;
    107.         OUT.worldPos = worldPos;
    108.  
    109.         // send extra vertex to forwardadd pass
    110.         unityTransferVertexToFragmentHack v;
    111.         v.vertex = vertexPos + mul(rotation, float3(width, height, curve) + float3(0, 0, offset));
    112.         TRANSFER_VERTEX_TO_FRAGMENT(OUT);
    113.         UNITY_TRANSFER_FOG(OUT, OUT.pos);
    114.  
    115.         return OUT;
    116.     }
    117.  
    118.     [maxvertexcount(51)]
    119.     void geom(point v2g IN[1], inout TriangleStream<g2f> triStream)
    120.     {
    121.         float forward = rand(IN[0].pos.yyz) * _BladeForward;
    122.         float3 lightPosition = _WorldSpaceLightPos0;
    123.  
    124.         float3 perpendicularAngle = float3(0, 0, 1);
    125.         float3 faceNormal = cross(perpendicularAngle, IN[0].norm) * lightPosition;
    126.  
    127.         float4 worldPos = mul(unity_ObjectToWorld, IN[0].pos);
    128.  
    129.         float distanceFromCamera = distance(worldPos, _WorldSpaceCameraPos);
    130.         float distanceFade = 1 - saturate((distanceFromCamera - _MinDist) / _MaxDist);
    131.  
    132.         float3 v0 = IN[0].pos.xyz;
    133.  
    134.         float3 wind1 = float3(sin(_Time.x * _WindSpeed + v0.x) + sin(_Time.x * _WindSpeed + v0.z * 2) + sin(_Time.x * _WindSpeed * 0.1 + v0.x), 0,
    135.             cos(_Time.x * _WindSpeed + v0.x * 2) + cos(_Time.x * _WindSpeed + v0.z));
    136.  
    137.         wind1 *= _WindStrength;
    138.  
    139.         _GrassHeight *= clamp(rand(IN[0].pos.xyz), 1 - _RandomHeight, 1 + _RandomHeight);
    140.  
    141.         for (int j = 0; j < (GrassBlades * distanceFade); j++)
    142.         {
    143.             float3x3 facingRotationMatrix = AngleAxis3x3(rand(IN[0].pos.xyz) * UNITY_TWO_PI + j, float3(0, 1, -0.1));
    144.             float3x3 transformationMatrix = facingRotationMatrix;
    145.             float radius = j / (float)GrassBlades;
    146.             float offset = (1 - radius) * _Rad;
    147.             for (int i = 0; i < GrassSegments; i++)
    148.             {
    149.                 float t = i / (float)GrassSegments;
    150.                 float segmentHeight = _GrassHeight * t;
    151.                 float segmentWidth = _GrassWidth * (1 - t);
    152.  
    153.                 segmentWidth = i == 0 ? _GrassWidth * 0.3 : segmentWidth;
    154.  
    155.                 float segmentForward = pow(t, _BladeCurve) * forward;
    156.  
    157.                 float3x3 transformMatrix = i == 0 ? facingRotationMatrix : transformationMatrix;
    158.  
    159.                 float3 newPos = i == 0 ? v0 : v0 + (wind1 * t);
    160.  
    161.                 triStream.Append(GrassVertex(newPos, segmentWidth, segmentHeight, offset, segmentForward, float2(0, t), transformMatrix, faceNormal, worldPos));
    162.                 triStream.Append(GrassVertex(newPos, -segmentWidth, segmentHeight, offset, segmentForward, float2(1, t), transformMatrix, faceNormal, worldPos));
    163.             }
    164.  
    165.             triStream.Append(GrassVertex(v0 + wind1, 0, _GrassHeight, offset, forward, float2(0.5, 1), transformationMatrix, faceNormal, worldPos));
    166.             triStream.RestartStrip();
    167.         }
    168.     }
    169.  
    170.     ENDCG
    171.  
    172.     SubShader
    173.     {
    174.         Cull Off
    175.  
    176.         Pass
    177.         {
    178.             Tags
    179.             {
    180.                 "RenderType" = "Geometry"
    181.                 "LightMode" = "ForwardBase"
    182.             }
    183.  
    184.             CGPROGRAM
    185.             #pragma vertex vert
    186.             #pragma fragment frag
    187.             #pragma geometry geom
    188.             #pragma target 4.6
    189.             #pragma multi_compile DIRECTIONAL POINT SPOT SHADOWS_DEPTH SHADOWS_SCREEN
    190.  
    191.             float4 _TopColor;
    192.             float4 _BottomColor;
    193.             float _AmbientStrength;
    194.  
    195.             float4 frag(g2f input) : SV_Target
    196.             {
    197.                 UNITY_LIGHT_ATTENUATION(atten, input, input.worldPos);
    198.  
    199. #ifdef POINT
    200.                 unityShadowCoord3 lightCoord = mul(unity_WorldToLight, unityShadowCoord4(input.worldPos, 1)).xyz;
    201.                 fixed shadow = UNITY_SHADOW_ATTENUATION(input, input.worldPos);
    202.                 atten = tex2D(_LightTexture0, dot(lightCoord, lightCoord).rr).r * shadow;
    203. #elif defined(SPOT)
    204.                 DECLARE_LIGHT_COORD(input, input.worldPos);
    205.                 fixed shadow = UNITY_SHADOW_ATTENUATION(input, input.worldPos);
    206.                 atten = (lightCoord.z > 0) * UnitySpotCookie(lightCoord) * UnitySpotAttenuate(lightCoord.xyz) * shadow;
    207. #endif
    208.  
    209.                 float4 baseColor = lerp(_BottomColor, _TopColor, saturate(input.uv.y));
    210.                 float3 ambient = ShadeSH9(float4(0, 1, 0, 1.0));
    211.                 float4 final = baseColor * atten * _LightColor0;
    212.                 final.rgb += (ambient * baseColor);
    213.                 return final;
    214.             }
    215.  
    216.             ENDCG
    217.         }
    218.        
    219.         Pass
    220.         {
    221.             Tags
    222.             {
    223.                 "LightMode" = "ForwardAdd"
    224.             }
    225.  
    226.             Blend One One
    227.             ZWrite Off
    228.  
    229.             CGPROGRAM
    230.             #pragma vertex vert
    231.             #pragma geometry geom
    232.             #pragma fragment frag                                  
    233.             #pragma multi_compile DIRECTIONAL POINT SPOT SHADOWS_DEPTH SHADOWS_SCREEN
    234.  
    235.             float4 _TopColor;
    236.             float4 _BottomColor;
    237.  
    238.             float4 frag(g2f input) : SV_Target
    239.             {
    240.                 UNITY_LIGHT_ATTENUATION(atten, input, input.worldPos);
    241. #ifdef POINT
    242.                 unityShadowCoord3 lightCoord = mul(unity_WorldToLight, unityShadowCoord4(input.worldPos, 1)).xyz;
    243.                 fixed shadow = UNITY_SHADOW_ATTENUATION(input, input.worldPos);
    244.                 atten = tex2D(_LightTexture0, dot(lightCoord, lightCoord).rr).r * shadow;
    245. #elif defined(SPOT)
    246.                 DECLARE_LIGHT_COORD(input, input.worldPos);
    247.                 fixed shadow = UNITY_SHADOW_ATTENUATION(input, input.worldPos);
    248.                 atten = (lightCoord.z > 0) * UnitySpotCookie(lightCoord) * UnitySpotAttenuate(lightCoord.xyz) * shadow;
    249. #endif
    250.  
    251.                 float4 baseColor = lerp(_BottomColor, _TopColor, saturate(input.uv.y));
    252.                 float3 ambient = ShadeSH9(float4(0, 1, 0, 1.0));
    253.                 float4 final = baseColor * atten * _LightColor0;
    254.                 final.rgb += (ambient * baseColor);
    255.                 return final;
    256.             }
    257.             ENDCG
    258.         }
    259.  
    260.         Pass
    261.         {
    262.             Tags
    263.             {
    264.                 "LightMode" = "ShadowCaster"
    265.             }
    266.  
    267.             CGPROGRAM
    268.             #pragma vertex vert
    269.             #pragma geometry geom
    270.             #pragma fragment frag
    271.             #pragma multi_compile_shadowcaster
    272.  
    273.             float4 frag(g2f i) : SV_Target
    274.             {
    275.                 SHADOW_CASTER_FRAGMENT(i)
    276.             }
    277.             ENDCG
    278.         }
    279.     }  
    280.     Fallback "VertexLit"
    281. }
    282.  
     
  2. MisterNebula

    MisterNebula

    Joined:
    Jun 23, 2020
    Posts:
    2
    Bumping, still haven't figured this out.