Search Unity

Question Need some help doing manual depth testing

Discussion in 'General Graphics' started by weiner_monkey, Jun 5, 2023.

  1. weiner_monkey

    weiner_monkey

    Joined:
    Aug 1, 2022
    Posts:
    49
    Unity 2021.3.15 LTS, URP

    I'm trying to implement manual depth testing in a shader, where items are being rendered with ZWrite Off and using CommandBuffer.DrawMesh(). The draw order is random and cannot be changed. I have created a rendertexture of type R16G16_UNORM to which I write to and read from. Here is a gist of the render loop:

    Code (CSharp):
    1.  buffer.SetRenderTarget(_frameBuffer1, 0, CubemapFace.Unknown, -1);
    2.                 buffer.ClearRenderTarget(true, true, Color.black);
    3.                 buffer.SetRenderTarget(
    4.                     new RenderTargetIdentifier[] { renderingData.cameraData.renderer.cameraColorTarget, _frameBuffer1 },
    5.                     renderingData.cameraData.renderer.cameraDepthTarget, 0, CubemapFace.Unknown, -1);
    6.  
    7.                 for(int i = 0; i < itemList.Count; ++i)
    8.                 {
    9.                     var item = itemList[i];
    10.                     item.ObjectRenderer.sharedMaterial.SetTexture(DepthLut, _frameBuffer1);
    11.  
    12.                     buffer.DrawMesh(item.ObjectRenderer.item.ObjectRenderer.sharedMaterial);
    13.                 }
    14.  
    and the shader fragment looks like:

    Code (CSharp):
    1.             struct PixelS
    2.             {
    3.                 float4 target0 : SV_Target0;
    4.                 float4 target1 : SV_Target1;
    5.             };
    6.            
    7.             PixelS SpriteFrag(v2f IN)
    8.             {
    9.                 PixelS val;
    10.                
    11.                 float2 screenUv = IN.screenPos.xy / IN.screenPos.w; //screen uvs
    12.                 float depth = IN.depth; //clip.z / clip.w
    13.  
    14.                 fixed4 d = tex2D(_DepthLut, screenUv.xy);
    15.                
    16.                 val.target0 = d; //to test value
    17.                 val.target1 = float4( 0., depth > d.y ? depth : d.y, 0., 0. );
    18.                
    19.                 return val;
    20.             }
    The objects that are rendered later appear on top even if they are behind, so the comparison in the shader doesnt seem to be taking place. I'm constrained not using a depth buffer here. Any ideas what I'm doing wrong and what I can do?
     
  2. c0d3_m0nk3y

    c0d3_m0nk3y

    Joined:
    Oct 21, 2021
    Posts:
    666
    Manual depth testing is not as easy as you think

    - You can't read from a render target that you are currently rendering to
    - You *can* use a RWTexture instead but that comes with some problems to:
    -- Slow because you don't get early-z rejection. This means, you'll be shading much more pixels than usually
    -- Multiple triangles are shaded in parallel. You have to use atomic writes.

    It might be better to make a copy of your depth buffer and bind that instead.

    Just some advice from one monkey to another ;)
     
    weiner_monkey likes this.
  3. weiner_monkey

    weiner_monkey

    Joined:
    Aug 1, 2022
    Posts:
    49
    Yep I guess Ill have to bind another depth target