Reuse depth buffer of Main Camera?

I’m developing a glow effect, having this test scene:

I have a secondary Camera rendering to a Target texture, only objects on Glow layer:

Now I want to cull fragments covered by Eiffel Tower. Of course I don’t want to draw all the 1M Eiffel Tower triangles again here. The idea is to reuse the depth texture of the Main Camera (I can get a sample from it using Unity - Scripting API: DepthTextureMode.Depth):


But I can’t see how to cull fragments in the secondary camera shader. The shader code is bare simple, my question is how to use _CameraDepthTexture in my shader:

Shader "eppz!/Glow/Camera"
{
    Properties
    {
        _MainColor ("Main Color", Color) = (1,1,1,1)
        _GlowColor ("Glow Color", Color) = (1,1,1,1)
    }

    SubShader
    {
        Pass
        {       
            CGPROGRAM

            #pragma vertex vert
            #pragma fragment frag

            fixed4 _MainColor;
            fixed4 _GlowColor;
            sampler2D_CameraDepthTexture;
   
            float4 vert(float4 v:POSITION) : SV_POSITION
            {
                // Sample from depth texture.
                // Compare to current vertex depth (But how?).
                // Discard fragment if Z-culled.
           
                return mul (UNITY_MATRIX_MVP, v);
            }

            fixed4 frag() : COLOR
            {
                // Sample here at least, then output black pixel if fragment is Z-culled.
                return _GlowColor;
            }

            ENDCG
        }
    }
}

Turned out that the best is to use GLSL, as it has gl_FragCoord showing me the exact fragment position (this is not entrely the same as I would calculated a z position from vertex position and projection).

Here is the lovely pass:


Draws only 2 sphere and a cube, but culled by the Eiffel Tower in the front.

Full composite with glow, overlay, and some more geometry:


The glow camera only draws the glowing objects before blur (see bottom right), but in the shader they are culled with scene depth buffer.

Shader goes like:

Shader "eppz!/Glow/Camera (GLSL)"
{
    Properties
    {
        _GlowColor ("Glow Color", Color) = (1,1,1,1)
    }

    SubShader
    {
        Pass
          {
            GLSLPROGRAM
     
            uniform vec4 _GlowColor;
     
            uniform vec4 _ScreenParams;
            uniform sampler2D _CameraDepthTexture;
                 
             varying vec2 v_textureCoordinates;      
     
            #ifdef VERTEX
            void main()
            {
                gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
                v_textureCoordinates = gl_MultiTexCoord0.xy;         
            }
            #endif

            #ifdef FRAGMENT
            void main()
            {
                vec2 fragmentScreenCoordinates = vec2(gl_FragCoord.x / _ScreenParams.x, gl_FragCoord.y / _ScreenParams.y);
                float sceneDepthSample = texture2D(_CameraDepthTexture, fragmentScreenCoordinates).x;
                bool culled = (sceneDepthSample < gl_FragCoord.z);
         
                // Output.
                gl_FragColor = (culled) ? vec4(0.0, 0.0, 0.0, 1.0) : _GlowColor;
            }
            #endif

            ENDGLSL
        }

Actually a manual Z-test.

5 Likes