US3S11L3——查看深度和法线纹理

查看深度纹理信息

我们可以在屏幕后期处理中使用我们学习过的获取深度信息的知识点,将深度值作为颜色的RGB值显示在屏幕上,感受深度纹理中存储的内容

理论上来说,如果深度值使用 0~1 范围的线性值,越接近近裁剪面越靠近黑色,越接近远裁剪面越靠近白色

实现 查看深度纹理屏幕后期处理效果 对应 Shader

  1. 新建 Shader,删除无用代码

  2. 声明变量

    在 Shader 中通过声明 _CameraDepthTexture​ 获取深度纹理

    1
    2
    3
    sampler2D _MainTex;
    float4 _MainTex_ST;
    sampler2D _CameraDepthTexture; // 按规则命名的深度纹理变量
  3. 顶点着色器

    只需要修改传入结构体类型

    1
    2
    3
    4
    5
    6
    7
    v2f vert (appdata_base v)
    {
    v2f o;
    o.vertex = UnityObjectToClipPos(v.vertex);
    o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
    return o;
    }
  4. 片元着色器

    使用深度纹理采样宏得到的结果是非线性的,将非线性的深度值转换到观察空间下,
    并将像素点到摄像机的距离转换到 [0,1] 区间内(线性深度值),将深度值作为返回颜色的RGB值

    1
    2
    3
    4
    5
    6
    7
    fixed4 frag (v2f i) : SV_Target
    {
    float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv); // 非线性的裁剪空间下深度值
    fixed linearDepth = Linear01Depth(depth); // 得到一个线性的0~1区间的深度值
    // 将深度值作为RGB颜色输入,越接近摄像机就越黑,越远离摄像机就越白,具体就会呈现出深浅灰
    return fixed4(linearDepth, linearDepth, linearDepth, 1);
    }
  5. Fallback Off

完整 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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
Shader "TeachShader/Lesson110"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag

#include "UnityCG.cginc"

struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};

sampler2D _MainTex;
float4 _MainTex_ST;
sampler2D _CameraDepthTexture; // 按规则命名的深度纹理变量

v2f vert (appdata_base v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
return o;
}

fixed4 frag (v2f i) : SV_Target
{
float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv); // 非线性的裁剪空间下深度值
fixed linearDepth = Linear01Depth(depth); // 得到一个线性的0~1区间的深度值
// 将深度值作为RGB颜色输入,越接近摄像机就越黑,越远离摄像机就越白,具体就会呈现出深浅灰
return fixed4(linearDepth, linearDepth, linearDepth, 1);
}
ENDCG
}
}

Fallback Off
}

实现 查看深度纹理屏幕后期处理效果 对应 C# 代码

  1. 新建 C# 脚本,命名和 Shader 相同

  2. 继承 PostEffect

    具体代码详见:US3S10L4——屏幕后处理基类

  3. Start​ 函数中设置深度纹理模式

1
2
3
4
5
6
7
8
9
10
using UnityEngine;

public class Lesson110_DepthTexture : PostEffect
{
void Start()
{
// 设置让Shader可以得到深度纹理信息
Camera.main.depthTextureMode = DepthTextureMode.Depth;
}
}

将该脚本挂载到摄像机后,在关联上文实现的 Shader 即可看到效果:

image

效果展示

原画面:

image

将摄像机的远裁剪面设置为100,将深度纹理显示在画面上,效果如下:

image

可见,屏幕上离摄像机越远的地方越白,离摄像机越近的地方越黑

查看法线纹理信息

我们可以在屏幕后期处理中用我们学习过的获取法线信息的知识点,将法线作为颜色显示在屏幕上,感受法线纹理中存储的内容

实现 查看法线纹理屏幕后期处理效果 对应 Shader

  1. 新建 Shader,删除无用代码

  2. 声明变量

    在 Shader 中通过声明 _CameraDepthNormalsTexture​ 获取深度+法线纹理

    1
    2
    3
    4
    5
    6
    7
    8
    9
    struct v2f
    {
    float2 uv : TEXCOORD0;
    float4 vertex : SV_POSITION;
    };

    sampler2D _MainTex;
    float4 _MainTex_ST;
    sampler2D _CameraDepthNormalsTexture; // 按规则命名的深度+法线纹理变量
  3. 顶点着色器

    只需要修改传入结构体类型

    1
    2
    3
    4
    5
    6
    7
    v2f vert (appdata_base v)
    {
    v2f o;
    o.vertex = UnityObjectToClipPos(v.vertex);
    o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
    return o;
    }
  4. 片元着色器

    对深度+法线纹理进行采样(其中xy是法线信息,zw是深度信息)
    使用 UnityCG.cginc​ 内置文件中的方法一次性处理深度和法线,得到深度值 (0~1) 和法线信息 (观察空间下)
    将法线的 [-1~1] 转换到 [0~1],作为颜色值输出

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    fixed4 frag (v2f i) : SV_Target
    {
    // 直接采样获取到裁剪空间下的屏幕法线+深度信息
    float4 depthNormal = tex2D(_CameraDepthNormalsTexture, i.uv);
    fixed depth;
    fixed3 normals;
    DecodeDepthNormal(depthNormal, depth, normals);
    // 将法线的-1到1之间的区间变换到0~1之间
    return fixed4(normals * 0.5 + 0.5, 1);
    }
  5. Fallback Off

完整 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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
Shader "TeachShader/Lesson111_DepthNormalTexture"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag

#include "UnityCG.cginc"

struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};

sampler2D _MainTex;
float4 _MainTex_ST;
sampler2D _CameraDepthNormalsTexture; // 按规则命名的深度+法线纹理变量

v2f vert (appdata_base v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
return o;
}

fixed4 frag (v2f i) : SV_Target
{
// 直接采样获取到裁剪空间下的屏幕法线+深度信息
float4 depthNormal = tex2D(_CameraDepthNormalsTexture, i.uv);
fixed depth;
fixed3 normals;
DecodeDepthNormal(depthNormal, depth, normals);
// 将法线的-1到1之间的区间变换到0~1之间
return fixed4(normals * 0.5 + 0.5, 1);
}
ENDCG
}
}

Fallback Off
}

实现 查看法线纹理屏幕后期处理效果 对应 C# 代码

  1. 新建 C# 脚本,命名和 Shader 相同

  2. 继承 PostEffect

    具体代码详见:US3S10L4——屏幕后处理基类

  3. Start​ 函数中设置深度纹理模式

1
2
3
4
5
6
7
8
9
10
using UnityEngine;

public class Lesson111_DepthNormalTexture : PostEffect
{
void Start()
{
// 设置让Shader可以得到深度纹理信息
Camera.main.depthTextureMode = DepthTextureMode.DepthNormals;
}
}

将该脚本挂载到摄像机后,在关联上文实现的 Shader 即可看到效果:

image

效果展示

原画面:

image

将法线纹理显示在画面上,效果如下:

image

可见,屏幕上每个像素点内的顶点法线方向不同,其呈现的颜色也不同,在同一平面上的点拥有相同的法线颜色
具体法线为何呈现出这样的颜色,可参考:US3S2L4——凹凸纹理基本概念