Search Unity

Shader access to shadow map

Discussion in 'Shaders' started by alephgames, Aug 23, 2010.

  1. alephgames

    alephgames

    Joined:
    Apr 6, 2010
    Posts:
    8
    Hello

    I'm writing some post process effects/shaders, and I need read acess to the shadow map texture.

    Has unity some built-in access to the shadow map texture, or I have to write my own procedure (i.e, render scene from light point of view)?

    I've seen that UnityCG.cginc has a sampler2D called _ShadowMapTexture, but is seems to be empty in my initial tests.

    Thanks in advance
     
  2. Aras

    Aras

    Unity Technologies

    Joined:
    Nov 7, 2005
    Posts:
    4,770
    No, there's no built-in way to access that. Part of the reason is that there can be more than one shadow map in the scene, so after scene is done, which one would you get?

    So yeah, rendering it manually from light's POV is the way to go.
     
  3. alephgames

    alephgames

    Joined:
    Apr 6, 2010
    Posts:
    8
  4. DerWoDaSo

    DerWoDaSo

    Joined:
    May 25, 2009
    Posts:
    131
    @Aras: Is it in general possible to access the shadow map (the depth value) inside the fragment shader of a regular (forward rendering) shader?
     
  5. flogelz

    flogelz

    Joined:
    Aug 10, 2018
    Posts:
    142
    I'm just posting this here , just in case someone stumbles across the same question! So I was also searching for a way to sample the screen space shadow texture with a commandbuffer and noticed, that they use this technique in the 3D GameKit from Unity! And it just seems to work straight out of the box this way! I saw many questions about this and nobody ever posted his working code, so here ya go!

    Code that should be attached to the main directional light:
    Code (CSharp):
    1. using UnityEditor;
    2. using UnityEngine;
    3. using UnityEngine.Rendering;
    4.  
    5. namespace Gamekit3D
    6. {
    7.     [ExecuteInEditMode]
    8.     public class CopyShadowMap : MonoBehaviour
    9.     {
    10.         CommandBuffer cb = null;
    11.  
    12.         void OnEnable()
    13.         {
    14.             var light = GetComponent<Light>();
    15.             if (light)
    16.             {
    17.                 cb = new CommandBuffer();
    18.                 cb.name = "CopyShadowMap";
    19.                 cb.SetGlobalTexture("_DirectionalShadowMask", new RenderTargetIdentifier(BuiltinRenderTextureType.CurrentActive));
    20.                 light.AddCommandBuffer(UnityEngine.Rendering.LightEvent.AfterScreenspaceMask, cb);
    21.             }
    22.         }
    23.  
    24.         void OnDisable()
    25.         {
    26.             var light = GetComponent<Light>();
    27.             if (light)
    28.             {
    29.                 light.RemoveCommandBuffer(UnityEngine.Rendering.LightEvent.AfterScreenspaceMask, cb);
    30.             }
    31.         }
    32.     }
    33. }
    And in the shader, access the map likes this:
    Code (CSharp):
    1. sampler2D _DirectionalShadowMask;
    and in the surf/fragment shader:
    Code (CSharp):
    1. float shadowmask = tex2D(_DirectionalShadowMask,screenUV).b;
    Theres also this Macro written there, but I'm not sure for what it's used:
    Code (CSharp):
    1. UNITY_DECLARE_SHADOWMAP(_DirectionalShadowMap);
    (I just didnt used it and it still worked) UPDATE: Also thanks to @bgolus for clearing this up:
    That's for defining a shadow map texture object ... which technically the screen space shadow texture is not so can be ignored. You've already defined it as a sampler2D, which is what it is.

    Anyways, I hope this helps someone!
     
    Last edited: Jul 22, 2019
    HeliosJack likes this.