文章目录
深度图原理
移步:深度测试,这篇文章讲了深度图的概念。
深度重建
深度图是经过NDC坐标空间后渲染出来的,深度存储时不是线性的,因此需要进行重建。幸运的是,Unity3D ShaderLab中提供了这个函数接口。
// vert
o.vertex = UnityObjectToClipPos(v.vertex); // mvp变换
o.screenPos = ComputeScreenPos(o.vertex); // 获取屏幕空间坐标
COMPUTE_EYEDEPTH(o.screenPos.z); // 获取模型在View空间的z
// frag
float screenZ = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(i.screenPos)));
float depth = Linear01Depth(SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(i.screenPos)));
深度写入
注意:RenderQueue <= 2450
。
Pass {
Name "ShadowCaster"
Tags { "LightMode" = "ShadowCaster" }
ZWrite On ZTest LEqual Cull Off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 2.0
#pragma multi_compile_shadowcaster
#include "UnityCG.cginc"
struct v2f {
V2F_SHADOW_CASTER;
UNITY_VERTEX_OUTPUT_STEREO
};
v2f vert(appdata_base v)
{
v2f o;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
return o;
}
float4 frag(v2f i) : SV_Target
{
SHADOW_CASTER_FRAGMENT(i)
}
ENDCG
}
一些遇到的坑
- 深度图 != 深度缓冲,深度图和深度缓存不同,zwrite off可以关闭写入深度缓存,但还会写入深度图。_CameraDepthTexture本身是渲染得到的屏幕纹理,和zwrite并没有直接联系。