Sorry, your browser cannot access this site
This page requires browser support (enable) JavaScript
Learn more >

深度纹理和法线的作用

一、为什么要使用深度和法线纹理

主要原因:


仅仅通过屏幕后处理的这种,基于获取当前屏幕中心的像素信息进行后处理的的效果
存在某些问题,导致无法实现某些效果 1. 效果欠佳
比如实现默写边缘检测效果时,边缘检测信息受物理纹理和光照等因素,无法更准确的检测边缘,会得到一些我们不需要的边缘点 2. 无法实现
比我们想要实现某些景深效果(虚化背景),我们无法通过像素的颜色颜色来判断离摄像机的远近

二、什么是深度和法线纹理

准确的说 指的是

  • 屏幕空间的深度纹理
    用于存储屏幕图像中的每个像素的深度信息的纹理
  • 屏幕空间法线纹理:
    用于存储屏幕空间中每个像素法线信息的纹理

三、深度和法线纹理的作用

主要作用: 是用于实现各种各样的我视觉效果,这些效果利用它们存储的深度和法线信息来增强真实感和细节 通过各种数据,就能进行更多不同的计算,就能做出更多的效果

两种纹理的实现的不同效果 - 深度纹理 可以利用其中存储的每个像素信息 制作出 边缘检测、运动模糊、景深、环境遮挡等等效果 - 法线纹理 可以利用其中存储的每个像素的法线信息 制作出 屏幕空间环境遮挡(SSAO)、基于屏幕空间的反射(SSR)、基于法线的边缘检测 等等效果

四、如何使用深度和法线纹理

  1. 让Unity知道我们需要使用深度和法线纹理
  2. 在Shader中直接声明对应的变量

CS部分

1
2
3
4
5
6
7
8
9
void 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);
}

评论