Search Unity

  1. Unity 2017.2 beta is now available for download.
    Dismiss Notice
  2. Unity 2017.1 is now released.
    Dismiss Notice
  3. Introducing the Unity Essentials Packs! Find out more.
    Dismiss Notice
  4. Check out all the fixes for 5.6 on the patch releases page.
    Dismiss Notice
  5. Help us improve the editor usability and artist workflows. Join our discussion to provide your feedback.
    Dismiss Notice

Reuse depth buffer of Main Camera?

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

  1. eppz

    eppz

    Joined:
    Aug 2, 2014
    Posts:
    89
    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:
    89
    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
    Daerst likes this.