Search Unity

Reuse depth buffer of Main Camera?

Discussion in 'Shaders' started by eppz, Nov 16, 2014.

  1. eppz

    eppz

    Joined:
    Aug 2, 2014
    Posts:
    172
    I'm developing a glow effect, having this test scene:

    Screen Shot 2014-11-16 at 17.28.46.png

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

    Screen Shot 2014-11-16 at 17.30.54.png

    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 http://docs.unity3d.com/ScriptReference/DepthTextureMode.Depth.html):

    Screen Shot 2014-11-16 at 17.30.10.png
    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:

    Code (CSharp):
    1. Shader "eppz!/Glow/Camera"
    2. {
    3.     Properties
    4.     {
    5.         _MainColor ("Main Color", Color) = (1,1,1,1)
    6.         _GlowColor ("Glow Color", Color) = (1,1,1,1)
    7.     }
    8.  
    9.     SubShader
    10.     {
    11.         Pass
    12.         {      
    13.             CGPROGRAM
    14.  
    15.             #pragma vertex vert
    16.             #pragma fragment frag
    17.  
    18.             fixed4 _MainColor;
    19.             fixed4 _GlowColor;
    20.             sampler2D_CameraDepthTexture;
    21.    
    22.             float4 vert(float4 v:POSITION) : SV_POSITION
    23.             {
    24.                 // Sample from depth texture.
    25.                 // Compare to current vertex depth (But how?).
    26.                 // Discard fragment if Z-culled.
    27.            
    28.                 return mul (UNITY_MATRIX_MVP, v);
    29.             }
    30.  
    31.             fixed4 frag() : COLOR
    32.             {
    33.                 // Sample here at least, then output black pixel if fragment is Z-culled.
    34.                 return _GlowColor;
    35.             }
    36.  
    37.             ENDCG
    38.         }
    39.     }
    40. }
     
    Last edited: Nov 16, 2014
  2. eppz

    eppz

    Joined:
    Aug 2, 2014
    Posts:
    172
    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:
    Yay!.png
    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:
    Screen Shot 2014-11-17 at 04.01.53.png
    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:
    Code (CSharp):
    1. Shader "eppz!/Glow/Camera (GLSL)"
    2. {
    3.     Properties
    4.     {
    5.         _GlowColor ("Glow Color", Color) = (1,1,1,1)
    6.     }
    7.  
    8.     SubShader
    9.     {
    10.         Pass
    11.           {
    12.             GLSLPROGRAM
    13.      
    14.             uniform vec4 _GlowColor;
    15.      
    16.             uniform vec4 _ScreenParams;
    17.             uniform sampler2D _CameraDepthTexture;
    18.                  
    19.              varying vec2 v_textureCoordinates;      
    20.      
    21.             #ifdef VERTEX
    22.             void main()
    23.             {
    24.                 gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
    25.                 v_textureCoordinates = gl_MultiTexCoord0.xy;        
    26.             }
    27.             #endif
    28.  
    29.             #ifdef FRAGMENT
    30.             void main()
    31.             {
    32.                 vec2 fragmentScreenCoordinates = vec2(gl_FragCoord.x / _ScreenParams.x, gl_FragCoord.y / _ScreenParams.y);
    33.                 float sceneDepthSample = texture2D(_CameraDepthTexture, fragmentScreenCoordinates).x;
    34.                 bool culled = (sceneDepthSample < gl_FragCoord.z);
    35.          
    36.                 // Output.
    37.                 gl_FragColor = (culled) ? vec4(0.0, 0.0, 0.0, 1.0) : _GlowColor;
    38.             }
    39.             #endif
    40.  
    41.             ENDGLSL
    42.         }
    43.  
    Actually a manual Z-test.
     
    Last edited: Nov 17, 2014