Reading depth in a simple HDRP shader

I’m trying to write a simple shader that blits the depth texture for use in a compute shader to implement Hi-Z occlusion culling.
It seems like the depth is read out wrong in my shader code though.
Here’s a simple comparison (1st image):

  • Left Cube has a material with an unlit, transparent shader graph.
  • Right Cube has a material with my shader code

Left is the result I’d expect. You can even see the depth verly lightly in the right image.

The shader graph (2nd image):

My shader code:

Shader "Unlit/NewUnlitShader"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        //Tags { "RenderType"="Opaque" }
        Tags
        {
            "RenderPipeline"="HDRenderPipeline"
            "RenderType"="HDUnlitShader"
            "Queue"="Geometry+0"
        }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
                float2 depth : TEXCOORD1;
                float4 scrPos : TEXCOORD2;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            sampler2D _CameraDepthTexture;

            v2f vert (appdata v)
            {
                v2f output;
                output.vertex = UnityObjectToClipPos(v.vertex);
                output.uv = TRANSFORM_TEX(v.uv, _MainTex);
  
                UNITY_TRANSFER_DEPTH(output.depth);
                output.scrPos = ComputeScreenPos(output.vertex);
  
                return output;
            }

            float4 frag (v2f i) : SV_Target
            {
                float camDepth = 1.0 - Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv));
                float4 col = float4(camDepth, camDepth, camDepth, 1.0);
                return col;
            }
            ENDCG
        }
    }
}


Class HDAdditionalCameraData | High Definition RP | 17.0.3 (unity3d.com)
I think you don’t need to write a custom shader at all.

1 Like

Thanks! That works.

Actually, I do need to write a shader. I have to reduce the depth buffer to build the HiZ Pyramid. So, back to the original question unfortunately.

Edit: So you actually have to create a new “HDRP Custom Renderers Pass” and assign a material with that shader in a “Custom Pass” component.
The old way to write simple vert & frag shaders apparently just doesn’t work in HDRP anymore?

You can use a custom pass to copy the depth buffer from the camera, or you can perform the calculations yourself in your shader:

    float4 clipPos = UnityObjectToClipPos(vertex);
    float zDepth = clipPos.z / clipPos.w;

You can use a custom renderers pass, but that method is more aimed at when you need to replace shaders or material at runtime (from what ive gathered). You can still just write a regular shader and make it do what you want. However, the custom pass framework is nice if you need other tricky, specific rendering.

In that case, what’s wrong with the original shader code I posted? It doesn’t look like it reads out the depth buffer correctly.

Seems like it does nothing in HDRP:

// Legacy; used to do something on platforms that had to emulate depth textures manually. Now all platforms have native depth textures.
#define UNITY_TRANSFER_DEPTH(oo)
// Legacy; used to do something on platforms that had to emulate depth textures manually. Now all platforms have native depth textures.
#define UNITY_OUTPUT_DEPTH(i) return 0

This shader will render the depth of objects in HDRP:

Shader "Render Depth" {
    SubShader {
        Tags { "RenderType"="Opaque" }
        Pass {
            CGPROGRAM

            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            struct v2f {
                float4 pos : SV_POSITION;
                float depth : TEXCOORD0;
            };

            v2f vert (appdata_base v) {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.depth = -UnityObjectToViewPos(v.vertex).z;
                return o;
            }

            half4 frag(v2f i) : SV_Target {
                return i.depth;
            }
            ENDCG
        }
    }
}
1 Like