- Home /
Problems with depth values in _CameraDepthTexture
I'm new to shader programming, so apologies if I am making some hugely noobish mistakes.
I'm trying to use a camera to simulate a Primesense style depth camera. My goal is to use the camera to capture the geometry and then have the fragment shader output a greyscale image where white = max distance and black = min distance. Distance is determined by looking up the fragment in the _CameraDepthTexture.
What I am actually seeing is that all fragments seem to have the same value -- a value of 1. I would be super appreciative if someone could explain how I am misusing the depth texture.
I will attempt to include all relevant pieces here:
The camera: FOV 53, Near plane 0.5, Far 10.
I am attaching a script that contains the following OnEnable, which sets a replacement shader to use for all objects in the scene (my depth shader):
void OnEnable()
{
Cam = GetComponentInChildren<Camera>();
if (Cam != null)
{
Cam.depthTextureMode = DepthTextureMode.Depth;
Cam.SetReplacementShader(ReplacementShader, "");
}
}
I modified the code of my shader to it's most basic form. We do the standard vertex bit, and then try to render the depth directly as a shade of grey.
Shader "Custom/DepthShader" {
Properties
{
}
SubShader
{
Pass
{
cull off
ZWrite On
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _CameraDepthTexture;
v2f_img vert( appdata_img v )
{
return vert_img(v);
}
float4 frag (v2f_img i) : COLOR
{
float d = tex2D(_CameraDepthTexture, i.uv.xy);
return float4(d,d,d,1);
}
ENDCG
}
}
FallBack "Diffuse"
}
Answer by JoeyK · Jun 12, 2012 at 09:33 PM
I've been trying to do essentially the same thing. Your code helped me get started so thank you. I eventually tried the demo shader on this page...and it worked. I feel kinda silly for spending so much time trying to get different combinations of other shaders to work when the answer was on that page the whole time.
Oh well, you've probably figured it out or given up by now but yeah... for the next guy.
I also changed the image effect script too:
#pragma strict
@script ExecuteInEditMode
@script RequireComponent (Camera)
class DepthCamEffect extends PostEffectsBase {
public var cam : Camera;
public var depth : Shader;
private var depthMaterial : Material = null;
function OnDisable()
{
if (depthMaterial)
DestroyImmediate(depthMaterial);
}
function CheckResources () : boolean {
CheckSupport (true);
depthMaterial = CheckShaderAndCreateMaterial (depth,depthMaterial);
if(!isSupported)
ReportAutoDisable ();
return isSupported;
}
function OnEnable(){
cam.depthTextureMode = DepthTextureMode.Depth;
cam.SetReplacementShader(depth, "");
}
}
And then just drag the camera and shaders you want to use into the spaces in the inspector.
What is the "image effect script" to which you are referring?
Answer by imangitarrowood · Feb 25, 2016 at 10:22 PM
I was having the same problem, so here's a years later answer for anyone else who comes looking for this: if you are using custom shaders, you need to make sure that you define a "ShadowCaster" pass for any that you want to write into the Unity depth texture (or fallback to a shader that does), even if it doesn't cast shadows (see http://docs.unity3d.com/Manual/SL-CameraDepthTexture.html under DepthTextureMode.Depth texture). Here's code to do that (copied from the old VertexLit shader).
// Pass to render object as a shadow caster, required to write to depth texture
Pass
{
Name "ShadowCaster"
Tags { "LightMode" = "ShadowCaster" }
Fog {Mode Off}
ZWrite On ZTest LEqual Cull Off
Offset 1, 1
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_shadowcaster
#include "UnityCG.cginc"
struct v2f
{
V2F_SHADOW_CASTER;
};
v2f vert( appdata_base v )
{
v2f o;
TRANSFER_SHADOW_CASTER(o)
return o;
}
float4 frag( v2f i ) : SV_Target
{
SHADOW_CASTER_FRAGMENT(i)
}
ENDCG
}
Answer by LeaveOneBlood · Nov 01, 2016 at 03:19 PM
hi,imangitarrowood ,I use your shader code,but I can not get the z-depth,as the result is all the objects in scene are disappeared。 how should i get the depth. thanks
The code that I posted was for writing depth if you are using custom shaders that don't fall back to Unity shaders for performance reasons. Reading depth is done how pmeade did it in the original question:
float d = tex2D(_CameraDepthTexture, i.uv.xy);
If that's not returning depth properly, make sure you have depth write enabled for the camera:
Cam = GetComponentInChildren();
if (Cam != null)
{
Cam.depthTexture$$anonymous$$ode = DepthTexture$$anonymous$$ode.Depth;
}
If you have everything set up right, you should be able to use the Frame Debugger in the editor to see the Projected Shadow pass clear the projectedShadow target and draw calls rendering to it under RenderForwardOpaque.Render. If that render target isn't there, your camera probably isn't set up to write depth. If the clear is there but no draw calls, then nothing drawn by that camera is using a shader with the ShadowCaster pass defined.
Hope that helps!
Answer by DynastyV · Dec 04, 2016 at 08:32 PM
Using
Tags{ "RenderType" = "Opaque" }
made it work for me