Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Resolved Cast shadows from differrent angle than recieve shadows

Discussion in 'Shaders' started by valtteri_m, Sep 14, 2020.

  1. valtteri_m

    valtteri_m

    Joined:
    Aug 6, 2014
    Posts:
    15
    I need a shader that recieves shadows normally,
    and casts shadows with the same mesh, but rotated towards the sun.

    Because my games has xy planes that always face the camera (on the xz axis), they cast shadows correctly only when they're facing the sun, meaning when the sun is behind the camera.
    Sun is behind:
    Sun is at side:


    I got a vert frag shader for the shadows. And there if I rotate the vertices in the ShadowCaster pass so that it's rotated towards the sun, It casts them correctly, but recieves them incorrectly.



    It's also worth noting that these planes are being rendered with Graphics.DrawMeshInstanced
     
  2. valtteri_m

    valtteri_m

    Joined:
    Aug 6, 2014
    Posts:
    15
    In the vert function of the ShadowCaster pass,
    I replaced UnityClipSpaceShadowCasterPos with it's source code which is:

    Code (CSharp):
    1. float4 UnityClipSpaceShadowCasterPos (float3 vertex, float3 normal) {
    2.     float4 clipPos;
    3.    
    4.     // Important to match MVP transform precision exactly while rendering
    5.     // into the depth texture, so branch on normal bias being zero.
    6.     if (unity_LightShadowBias.z != 0.0) {
    7.         float3 wPos = mul(unity_ObjectToWorld, float4(vertex,1)).xyz;
    8.         float3 wNormal = UnityObjectToWorldNormal(normal);
    9.         float3 wLight = normalize(UnityWorldSpaceLightDir(wPos));
    10.  
    11.     // apply normal offset bias (inset position along the normal)
    12.     // bias needs to be scaled by sine between normal and light direction
    13.     // (http://the-witness.net/news/2013/09/shadow-mapping-summary-part-1/)
    14.     //
    15.     // unity_LightShadowBias.z contains user-specified normal offset amount
    16.     // scaled by world space texel size.
    17.  
    18.         float shadowCos = dot(wNormal, wLight);
    19.         float shadowSine = sqrt(1 - shadowCos * shadowCos);
    20.         float normalBias = unity_LightShadowBias.z * shadowSine;
    21.  
    22.         wPos -= wNormal * normalBias;
    23.  
    24.         clipPos = mul(UNITY_MATRIX_VP, float4(wPos, 1));
    25.     }
    26.     else {
    27.         clipPos = UnityObjectToClipPos(vertex);
    28.     }
    29.     return clipPos;
    30. }
    The check if (unity_LightShadowBias.z != 0.0) determines if we are casting the shadow (basically). [Source]

    So for true, I have it rotate the vertices towards the sun,
    for false, I have it rotate the vertices towards the camera.


    This also causes the planes to cast shadows on themselves.

    Which is cool, but requires some fine tuning with the biases and shadow resolution to have a good looking result.


    Also, the reason why the shadows are in front of the imps in the earlier post's last image is because I had the sun's normal bias at zero.