Search Unity

PostProcess ScreenSpace Shadow Receiver?

Discussion in 'Shaders' started by zezba9000, Jul 7, 2017.

  1. zezba9000

    zezba9000

    Joined:
    Sep 28, 2010
    Posts:
    992
    I can sample the screen space shadow map on a Quad like so in the frag/pixel shader

    Code (csharp):
    1.  
    2. #define SHADOWS_SCREEN
    3.  #include "UnityCG.cginc"
    4.  #include "AutoLight.cginc"
    5.  
    6. // sample shadow in frag =
    7.  float shadow = unitySampleShadow(float4(i.uv.xy, 0, 1));
    8.  return shadow;
    9.  
    Trying to do shadow casting in a volumetric global fog shader.
    So why can't I sample the screen space shadow texture in a post process shader?

    If I have to do a full-screen quad with a grab pass and sample it like that, that would be silly.
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    Because Unity doesn't keep the screen space shadow texture, or shadow maps, bound after the opaque passes have finished. Why not? Because they decided to, really that's all there is to it.

    I think the usual trick is make a copy of the screen space shadow texture while it's still available, like using a command buffer on the directional light with the AfterScreenspaceMask light event. There's kind of an example of how to go about that here: https://gist.github.com/aras-p/03fa46fc0e92b9431806e61a5d26737c

    If you actually need the real shadow maps, and not just the screen space mask, it's a similar method but a little more involved. The Adam demo's volumetric lighting has an example for how to do that here: https://github.com/Unity-Technologies/VolumetricLighting
     
    shegway and zezba9000 like this.
  3. zezba9000

    zezba9000

    Joined:
    Sep 28, 2010
    Posts:
    992
    Tnx for the reference. Probably some combo of both those references you sent.

    (thinking out loud) To do this in a PostProcess effect, I will need to buffer the Shadow texture from a specific directional light with command buffers. Then figure out how to sample from it based on a XYZ position to get the shadow hit at a specific series of locations within the volume.
     
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    The screen space shadow map, what you would get with the "AfterScreenspaceMask" event, isn't going to be what you want then. It's not really a shadow map, it's a shadow mask. If you imagine a flat white scene with no lighting and just the shadows casting on stuff, that's what's in that texture. To get the shadow maps from the directional light takes a little more work ... and I think they deleted the code from the Adam VolumetricLighting repository as it was never officially enabled.

    This is probably more what you want.
    https://forum.unity3d.com/threads/true-volumetric-lights-now-open-source.390818/
     
  5. mradfo21

    mradfo21

    Joined:
    May 16, 2013
    Posts:
    194
    god i wish this was easier. I've got a working implementation of world position to directional light shadow but its painful and often times just doesn't work for no reason at all.

    that shadowmap is exposed with a command buffer. but man.. this is so awful. this is SUCH a common operation to want to perform too!


    float3 getShadow(float3 worldPosition){
    float4 shadowCoord0 = float4(mul(unity_WorldToShadow[0], float4(worldPosition,1)).xyz,1);
    if ( shadowCoord0.x < 0 || shadowCoord0.x >1 || shadowCoord0.y < 0 || shadowCoord0.y >1 ){
    return 1.0;
    }
    //do shadow test anshadowCoord0.x < 0 || shadowCoord0.x >1 d store the result
    float3 shadowTerm = UNITY_SAMPLE_SHADOW_PROJ(_SunShadow, shadowCoord0).xxx;
    return shadowTerm.xxx;
    }