深度测试是在模板测试之后

# 深度测试简要框架

所谓深度测试,就是针对当前对象在屏幕上 (更准确说是 frame buffer) 对应的像素点,将对象自身的深度值与当前该像素点缓存的深度值作比较,如果通过了,本对象在该像素点才会将颜色写入颜色缓冲。

  • 控制渲染顺序
    • 画家算法
    • Z-Buffer 算法
  • 控制 Z-Buffer 对深度的存储
    • Z Test
    • Z Write
  • 控制不同类型物体渲染顺序
    • 透明物体
    • 不透明物体
    • 渲染队列
  • 减少 overdraw
    • Early-Z
    • Z-Cull
    • Z-check

Z-Buffer 存储的是当前的深度信息,对于每个像素都会有一个深度值

通过 Z Write 和 Z Test 来调用 Z-Buffer, 实现想要的效果

深度写入包括两种状态: ZWrite On 与 ZWrite Off 当我们开启深度写入的时候,该物体会写入深度缓冲,否则不写入 但是,如果 ZWrite On 但是 Z Test 失败,也不会写入深度缓冲区 分为四种情况:

# 深度测试的状态

# 渲染队列

首先看一下 Unity 的几种内置渲染队列,按照渲染顺序,从先到后进行排序, 队列越小的,越先渲染,队列数越大的,越后渲染 不透明物体的渲染顺序,从前往后,透明的物体是从后往前 (overdraw) 所以透明物体会多渲染一次,产生性能上的问题

# Early-Z 技术

传统的渲染管线中,ZTest 其实是在片元着色器之后的,所以它是一定会执行的,而且如果测试失败,也会渲染一次,所以现代 GPU 优化了这个问题,现代 GPU 使用 Early-Z 技术,在顶点阶段和片元阶段之间进行一次检测,如果失败了,就不会继续执行片元的渲染。 深度测试 源码

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
51
52
53
54
55
Shader "ZTest/ZTest"
{
Properties{
[HideInInspector] _MainTex("Texture",2D) = "white" {}
_MainColor("Color",Color) = (1,1,1,1)
[Enum(off,0,on,1)]_ZWriteMode("ZWrite Mode",Float) = 1
[Enum(UnityEngine.Rendering.CompareFunction)]_ZComp("ZTest Comp",Float) = 4
}

SubShader{
Pass {
Tags {"RenderType" = "Opaque" "Queue" = "Geometry"}
ZWrite [_ZWriteMode]
ZTest [_ZComp]
Cull off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fog

#include "UnityCG.cginc"
struct appdata {
float4 vertex : POSITION;
float2 uv:TEXCOORD0;
};

struct v2f {
float2 uv:TEXCOORD0;
UNITY_FOG_COORDS(1)
float4 vertex : SV_POSITION;
};

sampler2D _MainTex;
float4 _MainTex_ST;
float4 _MainColor;

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

fixed4 frag(v2f i) : SV_Target{
half4 col = _MainColor;
UNITY_APPLY_FOG(i.fogColor, col);
return col;
}

ENDCG
}
}

}

# 可实现的效果

人物被遮挡时显示描边

不写入深度,但开启深度测试

实现思路,两个 Pass, 一个 Pass 正常渲染,另一个 Pass 在深度 Greater 时渲染为描边

这个代码可以见百人计划 1:23:30

# 深度测试扩展