Search Unity

Override depth sorting in fragment?

Discussion in 'Shaders' started by techmage, Jan 18, 2022.

  1. techmage

    techmage

    Joined:
    Oct 31, 2009
    Posts:
    2,133
    I am trying to write a shader where I could override the depth sorting in the fragment shader. So, if a piece of geometry is behind another piece of geometry in the vertex shader, in the fragment shader I could say a fragment on the distant geometry is actually closer and then it would render it on top of other geometry.

    Is that even possible?

    I have figured out how to override depth technically:

    struct fragOutput {
    fixed4 color : SV_Target;
    float depth:SV_Depth;
    };

    fragOutput frag (v2f i) : SV_Target
    {
    fragOutput o;
    o.color = tex2D(_MainTex, i.uv);
    o.depth = whatever;
    return o;
    }

    But seems no matter what I set o.depth to it will always render that fragment in the order that was determined by the actual positions of the geometry in the vertex shader. Is there some other flags I have to set?

    I tried
    ZTest Off
    ZWrite On

    But that didn't do it.
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
    Overriding the depth in the fragment shader should absolutely work, but the depth value you need to use may not be an intuitive value. It can also depend heavily on draw order, especially if you still use ZWrite.

    There are also ways to do this in the vertex shader that can be far more efficient if you don't need to be able to have a different depth value per pixel.


    Now to answer the actual question, just using
    ZTest Always
    will make something always draw ignoring the depth buffer, effectively having it draw "on top". However if it's not the last "thing" in the draw order it might still get drawn on top of, so you need to also modify the material's queue to be a higher value than the material on the object you want it to draw on top of.

    Alternatively if you want use the depth to handle this, for Windows you'll want the value you output as depth to be closer to 1 than the object you want to draw on top of, as a depth of 1.0 is the near plane and 0.0 is the far plane. It's also a non-linear value so "0.5" isn't half way between the near and far plane but somewhere much, much closer to the camera (depending on the projection's FOV).