US3S11L1——屏幕深度和法线纹理的使用
US3S11L1——屏幕深度和法线纹理的使用
深度和法线纹理的使用
使用屏幕深度和法线纹理,一般分两步:
-
让 Unity 知道我们需要使用深度和法线纹理
1
2
3
4
5
6private void Start()
{
Camera.main.depthTextureMode = DepthTextureMode.Depth; // 获取一张深度纹理
Camera.main.depthTextureMode = DepthTextureMode.DepthNormals; // 获取一张深度+法线纹理
Camera.main.depthTextureMode = DepthTextureMode.Depth | DepthTextureMode.DepthNormals; // 获取深度纹理 和 深度+法线纹理
} -
在 Shader 当中直接声明对应变量
-
深度纹理
1
sampler2D _CameraDepthTexture;
-
深度+法线纹理:
其中,
_CameraDepthNormalsTexture.rg
一般存储屏幕法线消息,_CameraDepthNormalsTexture.ba
一般存储屏幕深度消息1
sampler2D _CameraDepthNormalsTexture;
之后直接在 Shader 中使用这两个变量便可以获取到相关信息
-
使用深度和法线纹理需要的内置函数
对于以下内置函数的原理,详见:US3S11L2——深度和法线纹理背后的原理
-
获取深度纹理的深度值
首先需要使用
SAMPLE_DEPTH_TEXTURE()
宏对_CameraDepthTexture
采样,此时得到的采样结果是非线性的,
然后,使用LinearEyeDepth()
将非线性的深度值转换到观察空间下,
或者,使用Linear01Depth()
将采样结果转换为 [0,1] 区间内的线性深度值(此方法不需要和LinearEyeDepth()
配合使用!)1
2
3
4
5
6fixed4 frag(v2f i) : SV_Target
{
float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv); // 使用基本深度纹理采样,得到的结果是非线性的
float viewDepth = LinearEyeDepth(depth); // 将非线性的深度值转换到观察空间下
float linearDepth = Linear01Depth(depth); // 将非线性的深度值转换为[0,1]区间内的线性深度值
} -
获取深度+法线纹理的法线消息
其中,
DecodeViewNormalStereo()
是UnityCG.cginc
内置文件中的方法,用于同时得到深度值和法线消息
而DecodeFloatRG()
可以单独得到深度值,DecodeViewNormalStereo()
可以单独得到法线消息1
2
3
4
5
6
7
8
9fixed4 frag(v2f i) : SV_Target
{
float depth; // 用于存储深度值的变量
float3 normals; // 用于存储法线的变量
float4 depthNormal = tex2D(_CameraDepthNormalsTexture, i.uv); // 对深度+法线纹理进行采样(xy是法线消息,zw是深度消息)
DecodeDepthNormal(depthNormal, depth, normals); // 一次处理得到深度值和法线消息
depth = DecodeFloatRG(depthNormal.zw); // 单独得到深度值
normals = DecodeViewNormalStereo(depthNormal); // 单独得到法线消息
}
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 文KRIFE齐的博客!