深度纹理和法线的作用
一、为什么要使用深度和法线纹理
主要原因:
仅仅通过屏幕后处理的这种,基于获取当前屏幕中心的像素信息进行后处理的的效果
存在某些问题,导致无法实现某些效果 1. 效果欠佳
比如实现默写边缘检测效果时,边缘检测信息受物理纹理和光照等因素,无法更准确的检测边缘,会得到一些我们不需要的边缘点 2. 无法实现
比我们想要实现某些景深效果(虚化背景),我们无法通过像素的颜色颜色来判断离摄像机的远近
二、什么是深度和法线纹理
准确的说 指的是
- 屏幕空间的深度纹理
用于存储屏幕图像中的每个像素的深度信息的纹理 - 屏幕空间法线纹理:
用于存储屏幕空间中每个像素法线信息的纹理
三、深度和法线纹理的作用
主要作用: 是用于实现各种各样的我视觉效果,这些效果利用它们存储的深度和法线信息来增强真实感和细节 通过各种数据,就能进行更多不同的计算,就能做出更多的效果
两种纹理的实现的不同效果 - 深度纹理 可以利用其中存储的每个像素信息 制作出 边缘检测、运动模糊、景深、环境遮挡等等效果 - 法线纹理 可以利用其中存储的每个像素的法线信息 制作出 屏幕空间环境遮挡(SSAO)、基于屏幕空间的反射(SSR)、基于法线的边缘检测 等等效果
四、如何使用深度和法线纹理
- 让Unity知道我们需要使用深度和法线纹理
- 在Shader中直接声明对应的变量
CS部分 1
2
3
4
5
6
7
8
9void Start()
{
//获取深度纹理(一张纹理)
Camera.depthTextureMode = DepthTextureMode.Depth;
//获取深度+法线纹理(一张纹理)
Camera.depthTextureMode = DepthTextureMode.DepthNormals;
//获取深度+法线纹理(两种纹理)
Camera.depthTextureMode = DepthTextureMode.Depth | DepthTextureMode.DepthNormals;
}
Shader部分 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32//深度纹理
sampler2D _CameraDepthTexture;
//深度+法线纹理
sampler2D _CameraDepthNormalsTexture;//(一般RG通道存储法线,BA通道存储深度)
//深度纹理获取
fixed4 frag1(v2f i) SV_Target
{
//使用基本深度纹理采样 得到的结果是非线性的
float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.uv);
//将非线性的深度值 转换到观察空间下
float viewDepth = LinearEyeDepth(depth);
//将非线性的深度值 转换到[0,1]区间内的线性深度值
float linearDepth = Linear01Depth(depth);
}
//深度和法线纹理获取
fixed4 frag2(v2f i) SV_Target
{
//用于存储深度值的变量
float depth;
//用于存储法线值的变量
float normals;
//对深度+法线纹理进行采样(其中xy是法线信息,zw是深度信息)
float4 depthNormal = tex2D(_CameraDepthNormalsTexture,i.uv);
//UnityCG.cginc 内置文件的方法 用于得到深度值(0~1)和法线信息(观察空间下)
//相当于处理一次深度和法线信息
DecodeDepthNormal(depthNormal,depth,normals);
//DecodeDepthNormal的作用相当于下面两个函数的作用
//单独得到深度
depth = DecoedeFloatRG(depthNormals.zw);
//单独得到法线
normals = DecodeViewNormalStereo(depthNormal);
}