Search Unity

Is it possible to modify the Z-Buffer after z test?

Discussion in 'Shaders' started by Xavierseal, Apr 3, 2020.

  1. Xavierseal

    Xavierseal

    Joined:
    Oct 31, 2016
    Posts:
    7
    I actually want to clear a pixel's depth, so that anything renders after this pixel, will not be discarded no matter how deep it is in the scene.
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
    You can output a depth from the fragment shader to set it to whatever value you want, but whether you can set this after
    ZTest
    (early z rejection) depends on what graphics API you’re targeting.

    If you’re on PC desktop, you might be able to use the
    SV_DepthLessEqual
    or
    SV_DepthGreaterEqual
    fragment shader output semantic. This will let you output a custom depth value while still keeping the early z rejection based on the geometry depth. Some complications with this are you need to be using the matching
    ZTest
    , and Unity may flip that based on the current API and camera setup! Unity uses an reversed depth buffer for non-OpenGL platforms, so you actually want
    SV_DepthGreaterEqual
    most of the time. You can choose the correct one based on the
    UNITY_REVERSED_Z
    shader keyword.

    There’s also no guarantee that either of those two semantics will actually work properly on anything not Direct3D. I think they all support similar functionality, but the cross compilers might not translate it properly. You’re also probably not going to be able to use this if you’re looking to do this on mobile.


    The other option is to use two passes and stencils. Render the geometry once with a
    Stencil
    block that writes to the stencil buffer, and probably renders the object’s shader normally otherwise, if anything. Then a second pass that renders using
    ColorMask 0 ZTest Always
    and a
    Stencil
    block that only renders it where the previous pass was rendered (and clears the stencil on render) and have that use
    SV_Depth
    as an output semantic. That’ll work on basically everything. Just be sure to be outputting a depth value that matches that reversed Z keyword. 0.0 is the far depth when using the reversed z buffer.