Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

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:
    45
    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:
    529
    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:
    45
    Yep I guess Ill have to bind another depth target