Search Unity

  1. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

Clip texture based on depth buffer

Discussion in 'Shaders' started by dreamfeeel, Aug 22, 2012.

  1. dreamfeeel


    Aug 22, 2012
    Hi all,

    I'm working on effect whereby dynamic transparent objects moving behind a plane cut holes in it where they would otherwise be seen. If anyone could give me a point in the right direction I would be enormously appreciative.

    This is an effect I had working in DirectX which I really want to recreate in Unity (here's a picture). For that I wrote and read from the stencil buffer which of course isn't possible here.

    Right now I'm first just trying to draw the camera's depth texture to a plane, proving it works, and then I can hopefully cull pixels based on this texture (I would really appreciate any help with this too). Unfortunately I'm only getting an empty texture right now (despite there being a few objects in the scene).

    I have a script attached to the camera which calls camera.depthTextureMode = DepthTextureMode.Depth; on Update() every frame and this is the shader I'm using (taken from this thread) to render to the plane .

    Code (csharp):
    1. Shader "Custom/Render depth buffer" {
    2.     SubShader {
    3.         Tags { "RenderType"="Opaque" }
    4.         Pass {
    5.             Fog { Mode Off }
    7.         CGPROGRAM
    8.         #pragma vertex vert
    9.         #pragma fragment frag
    10.         #include "UnityCG.cginc"
    12.         uniform sampler2D _CameraDepthTexture;
    14.         struct v2f {
    15.             float4 vertex : POSITION;
    16.             float2 texcoord : TEXCOORD0;
    17.         };
    19.         v2f vert( v2f v ) {
    20.             v2f o;
    21.             o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
    22.             o.texcoord = v.texcoord;
    23.             return o;
    24.         }
    26.         half4 frag(v2f i) : COLOR
    27.        {
    28.             return tex2D(_CameraDepthTexture, i.texcoord);
    29.         }
    30.        ENDCG
    32.         }
    33.    }
    34.     FallBack Off
    35. }
    I realised I could do it with RenderTexture as well, but I'd prefer not to use that as I do not have Unity Pro unfortunately. I am running the trial however now and tried some solutions briefly with that, but again I was only getting a blank, gray texture. Any thoughts where I'm going wrong? Let me know if you'd like more information about anything.

    Sincere thanks for any help,

    (Dell XPS: Core i7-2860QM 2.5 GHz, GeForce GT 555M)
  2. BIG-BUG


    Mar 29, 2009
    Why not just use the z-buffer?

    If you can't use the z-buffer or you want soft blending, you could use the alpha channel as substitute for a stencil buffer:
    1. Render background
    2. Render your mask sprites with "ColorMask A"
    3. Render front layer using the destination alpha channel for blending: Blend DstAlpha OneMinusDstAlpha
  3. dreamfeeel


    Aug 22, 2012
    Thanks, this works. However, using the z-buffer this way means the mask must be in front of the object, I would like to be able to put the masks behind as they will all be moving at various depths. Is it possible to reverse it any way? I could possibly move the foreground behind all the masks and move it with the camera to simulate it being closer but I'm sure there's something less hacky.

    It'd be nice to get it to work with the depth mask as it will leave the foreground free for an existing shader, but I started to try working with the colour mask too. Currently I'm only getting it to draw the foreground where the masks are instead of where they aren't. I realise I'm probably missing something hugely obvious here, but I'm a total newcome to this shader business (and Unity) so apologies! Here's the two very simple shaders I'm using if you can see where I'm going wrong.

    For masking objects:
    Code (csharp):
    1. Shader "Masked/AlphaMask" {
    3.     SubShader {
    4.         Tags {"Queue" = "Geometry+10" }
    6.         ColorMask A
    7.         ZWrite On
    9.         Pass {}
    10.     }
    11. }
    And the masked foreground:
    Code (csharp):
    1. Shader "Custom/Masked" {
    2.     Properties {
    3.         _MainTex ("Base (RGB)", 2D) = "white" {}
    4.     }
    5.     SubShader {
    6.         Tags { "RenderType"="Opaque" }
    7.         LOD 200
    9.         Blend DstAlpha OneMinusDstAlpha
    10.         CGPROGRAM
    11.         #pragma surface surf Lambert
    13.         sampler2D _MainTex;
    15.         struct Input {
    16.             float2 uv_MainTex;
    17.         };
    19.         void surf (Input IN, inout SurfaceOutput o) {
    20.             half4 c = tex2D (_MainTex, IN.uv_MainTex);
    21.             o.Albedo = c.rgb;
    22.             o.Alpha = 0;
    23.         }
    24.         ENDCG
    25.     }
    26.     FallBack "Diffuse"
    27. }
    Thanks! :)
    Last edited: Aug 22, 2012
  4. aubergine


    Sep 12, 2009
    if you dont have unity pro, your camera will not produce a depth texture at all because its basically a render texture itself.
    you mentioned about pro trial, you should not call the camera.depthTextureMode = DepthTextureMode.Depth on every update(), just call it once at start() or awake().

    I suggest you read the Camera's Depth Texture from the refference manual and examine the mentioned unitycg.cginc file(related encoding and decoding functions), ssao and edge detection shaders inorder to learn how to use it.

    Also, check the builtin shader sources where there is the source of cameras depth texture shader. Its just a replacement shader which you can write your own custom one easily.

    EDIT: Your first initial shader should work (show you some siluette if you are on PRO trial), just make the cameras far clip plane a smaller value if you just want to see distinct colors on screen.
    Last edited: Aug 23, 2012
  5. dreamerflyer


    Jun 11, 2011
    Hi PaulMcG,this can make soft alpha mask sprite with gradient alpha?How make?