Search Unity

Bug In deferred rendering in the builtin pipeline,replacing "_ShadowMapTexture" w/ command buffer broken

Discussion in 'Shaders' started by funkyCoty, Nov 29, 2020.

  1. funkyCoty

    funkyCoty

    Joined:
    May 22, 2018
    Posts:
    727
    The following command buffer WORKS with replacing a directional light's _ShadowMapTexture in Forward rendering, in the builtin render pipeline. However, in the Deferred rendering mode, it does NOT work.

    Code (CSharp):
    1. command.SetGlobalTexture("_ShadowMapTexture", _texture);
    2. command.SetGlobalVector("_LightShadowData", ...);
    3. command.EnableShaderKeyword("SHADOWS_SCREEN");
    I believe this is an error. It seems that, only in deferred, these values are overridden.

    In Forward, I was using CameraEvent.BeforeForwardOpaque. In deferred, I tried both CameraEvent.BeforeLighting (both _ShadowMapTexture and _LightShadowData get overriden) and LightEvent.BeforeScreenspaceMask (only _ShadowMapTexture gets overriden?!).
     
  2. whitexroft

    whitexroft

    Joined:
    Oct 22, 2012
    Posts:
    48
    It is assumed that when your command buffer is done executing, the state is being returned, so ShadowMapTexture is set back to unity's native temporary texture.
    In my project I had to define an extra shadowmap, sample both, and take a minimum value
    Another option would be drawing manually a pyramide (for spot light, sphere for points) in your command buffer, exacty the same way as unity does it natively. Most of the data that unity light uses is being preserved, and you can use that.
     
  3. funkyCoty

    funkyCoty

    Joined:
    May 22, 2018
    Posts:
    727
    The behavior between Forward and Deferred are different, so one of them must be "wrong." In your explanation, it sounds like Forward is actually the one that is wrong, and I'm incorrect in wanting Deferred to behave the way Forward does, in this instance?
     
  4. whitexroft

    whitexroft

    Joined:
    Oct 22, 2012
    Posts:
    48
    I can't say why it is like this, and believe me I've had my share of frustrationt too :)
    So far my understanding is that there is no way to natively replace the _ShadowMapTexture in deferred, due to behind the scenes render states setting up. Most probably the reason is that in forward they bind their native texture to "_ShadowMapTexture" property just once, when they render the shadowmap. After that they call drawing of objects in the scene. In deferred, they they probably bind texture again, when they are calling the deferred light pass. Like this

    Graphics.SetGlobalTexture(_ShadowMapTexture, nativemap)
    Graphics.Draw // shadowmap
    [your command buffer here]
    Graphics.SetGlobalTexture(_ShadowMapTexture, nativemap)
    Graphics.Draw // light source

    Btw, what I also tried, and had it working alright, is blitting my custom shadowmap into _ShadowMapTexture at BeforeShadpwMap event.
    You just copy it as is, and then unity renders whatever afterwards
    I had to move from this solution only because blitting is expensive on low spec platforms, and set a separate shadowmap texture instead.
     
    Last edited: Dec 13, 2020
  5. funkyCoty

    funkyCoty

    Joined:
    May 22, 2018
    Posts:
    727
    I see. Yeah, that makes sense. Blitting is a okay compromise, I guess that might be the way to go for my thing.