Search Unity

Depth Texture needs Directional Lighting?

Discussion in 'Shaders' started by csofranz, Dec 6, 2019.

  1. csofranz

    csofranz

    Joined:
    Apr 29, 2017
    Posts:
    1,556
    I was fooling around with the depth texture when I came across something unexpected that I'm sure has a simple explanation, but has me baffled. What I'm doing is sample the depth texture at each frag, and use that value (0..1 non-linear depth value, 0 being far, 1 near pane) as the pixle's color (optionally mulitplied with a factor to make it a bit brighter (see shader, below)

    Put on a quad, I can see the objects behind the quad in greyscale, as expected. Until, that is, I switch the scene's one directional light off. Then suddenly, the entire quad turns white (indicating all pixels are on the near pane), even if there are point lights distributed in the scene

    So, my simple question is: why? What am I missing?

    With directional light:
    upload_2019-12-6_18-38-14.png

    Shader:
    Code (CSharp):
    1. Shader "Unlit/zbuffer2color"
    2. {
    3.        Properties
    4.     {
    5.         _Magnify ("Magnify", Range(1, 100))= 50    
    6.     }
    7.  
    8.     SubShader
    9.     {
    10.         Tags { "Queue"="Transparent" "RenderType"="Transparent" }
    11.  
    12.         Pass
    13.         {
    14.             Cull Off
    15.             ZWrite Off
    16.             Blend SrcAlpha OneMinusSrcAlpha
    17.  
    18.             CGPROGRAM
    19.             #pragma vertex vert
    20.             #pragma fragment frag
    21.          
    22.             #include "UnityCG.cginc"
    23.  
    24.             struct appdata
    25.             {
    26.                 float4 vertex : POSITION;
    27.                 float2 uv : TEXCOORD0;
    28.             };
    29.  
    30.             struct vert2frag
    31.             {
    32.                 float4 vertex : SV_POSITION;
    33.                 float4 screenPosRaw : TEXCOORD2;
    34.                 float eyeZ : TEXCOORD3;
    35.             };
    36.  
    37.             sampler2D _CameraDepthTexture;        
    38.             float _Magnify;
    39.          
    40.             vert2frag vert (appdata v)
    41.             {
    42.                 vert2frag o;
    43.                 o.vertex = UnityObjectToClipPos(v.vertex);
    44.                 o.screenPosRaw = ComputeScreenPos(o.vertex);
    45.                 return o;
    46.             }
    47.          
    48.             fixed4 frag (vert2frag i) : SV_Target
    49.             {            
    50.                 float4 screenPosRefined = UNITY_PROJ_COORD(i.screenPosRaw);
    51.                 float opaqZRaw = SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, screenPosRefined) * _Magnify;
    52.                 float4 color = float4(opaqZRaw, opaqZRaw, opaqZRaw,1);
    53.                 return color;
    54.             }
    55.             ENDCG
    56.         }
    57.     }
    58. }
     
    IgorAherne likes this.
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,348
    By default the camera depth texture is disabled. However some of Unity's built in rendering systems make use of it and it gets forced on even if it's disabled on the camera. Directional light shadows on desktop & consoles, and enabling soft particles in the quality settings are the two cases where the camera depth texture is forced on. If you run on a mobile device, directional light shadows don't make use of the camera depth texture and thus it won't be enabled on those platforms either.

    If you want the depth texture to be enabled regardless of the shadows, quality settings, or platform, you need to enable the depth texture mode on the camera via script.
    https://docs.unity3d.com/ScriptReference/Camera-depthTextureMode.html
    https://forum.unity.com/threads/no-...ng-when-shadows-disabled.519230/#post-3404030
     
    csofranz likes this.
  3. csofranz

    csofranz

    Joined:
    Apr 29, 2017
    Posts:
    1,556
    Ah, ideed. Thank you so much for that clarification. I did read the documentation, but completely misinterpreted the section about having to write a script to set the camera's depth texture. For later reference: here's a short script that you can attach to your scene manager to activate the depth texture upon Start()

    On hindsight, this also explains why the water shader I wrote (it calculates the color and transparency by depth) never functioned on an indoor (non-directionally lit) scene.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class setCamDepth : MonoBehaviour
    6. {
    7.  
    8.     public Camera theCamera;
    9.  
    10.     // Start is called before the first frame update
    11.     void Start() {
    12.         if (theCamera == null) {
    13.             theCamera = Camera.main;
    14.         }
    15.  
    16.         theCamera.depthTextureMode = DepthTextureMode.Depth;
    17.     }
    18.  
    19.  
    20. }
    Cheers,
    -ch