一、深度测试
fs-Alpha Test-Stencil Test-==Depth Test==
解决物体可见遮挡性的问题

因为测试阶段发生在fs之后,片元即便被丢弃,已经经过了fs中大量的无用的计算。
二、提前深度测试Early-Z
- 解决过多不必要的片元计算问题
- 光栅化-==EarlyZ==-fs-Alpha Test-Stencil Test-==Depth Test==

- EarlyZ也可以基于模板测试在着色前丢弃片元
- EarlyZ剔除的最小单位不是1像素,而是像素块(2x2)
2.1 EarlyZ失效
通常在EarlyZ阶段不仅会进行深度测试,还会写入深度
- 开启ALpha Test或Clip/discard等手动丢弃片元操作
- 如果手动丢弃片元,导致如果前面的片元丢弃了,深度仍然存在,后续的像素也会被丢弃。
- 手动修改GPU插值得到的深度
- 开启Alpha Blend
- 开启Alpha Blend的物体一般不会开启深度写入ZWrite off
- 关闭深度测试Depth Test
- 开启Multi-Sampling:多重采样会影响周边像素,而EarlyZ无法得知周边像素是否被裁剪,无法提前剔除
- 以及其他任何导致需要混合后面颜色的操作
此外,Early-Z技术会导致**深度数据冲突(depth data hazard)**的问题

避免深度数据冲突的方法之一是在写入深度值之前,再次与frame buffer的值进行对比:

2.2 高效利用EarlyZ
将不透明物体由近向远渲染,EarlyZ的优化效果最好
- CPU进行深度排序
- 场景复杂时,排序消耗增大。
- 严格按照从近到远渲染,不能同时搭配合批优化手段

三、使用Z-Prepass
- 在第一个pass即Z-Prepass中只写入深度,不计算输出任何颜色
- 自动计算了最小深度的zbuffer,无需cpu排序
- EarlyZ阶段也可以提升一点效率,虽然本来就没什么计算
- 第二个pass关闭深度写入,并且将深度比较函数设置为相等
1 | SubShader { |
四、Z-Prepass带来的问题
4.1 动态批处理问题
多pass的shader无法进行动态批处理-增加drawcall
解决方法:提前分离的PrePass
仍然使用两个pass
- 将原先第一个pass(Z-Prepass)单独分离出来为单独一个shader,并使用这个shader将整个场景的Opaque物体渲染一遍(写入深度)
- 原先材质只剩下原先的第二个Pass,仍关闭深度写入,并且深度比较函数设置为相等
两个pass都能够分别被批处理
4.2 Z-Prepass解决透明渲染
不写入深度的透明渲染会出现深度穿插错误的问题
(无法看到透明物体的背面)
- 如果要用Z-Prepass同时渲染物体背面
- 需要先渲染背面,剔除正面
- 在下一个pass渲染正面,剔除背面
- 可用于头发渲染
4.3 其他问题
计算消耗
权衡片元计算复杂性/overdraw与Z-Prepass的消耗,根据实际情况采用
五、Early-Z与Z-Prepass的实例应用
https://www.cnblogs.com/jaffhan/p/7382106.html



作业
- 做下preZ的效果测试
左边的狮子是preZ,右边的狮子是普通的Alpha。

因为是透明渲染,所以自然而然会想到preZ的方法能否应用到之前深度测试的透视效果。
因为preZ记录了最前面的一个深度。透视,也就是说透明物体前面被遮挡住了,并且已经绘制了这个遮挡物体,那么就是遮挡物体的深度写入了深度缓冲。我们也就没有了被遮挡物体最近面的深度了。而之后要绘制出来,也要用Greater的判定方式,最终透明物体无法表现出自遮挡。
并且如果没有遮挡物的时候,物体自身最近片元就写入了深度。那么物体自己对自己形成遮挡,最后会发生没有遮挡时,绘制出了物体自身重叠部分。这种没有对透视效果做特殊处理,所以最后一次绘制物体自身的时候会覆盖(这是深度缓冲依然是物体自身最近距离,测试规则为LEqual)但是如果透视部分有特殊效果,那么正常的物体渲染可能会漏出这一部分。
总之结论就是,这个效果同一物体多pass的实现方法,无法用preZ来完成。
- 总结earlyZ的限制
EarlyZ-失效
- 开启ALpha Test或Clip/discard等手动丢弃片元操作
- 如果手动丢弃片元,导致如果前面的片元丢弃了,深度仍然存在,后续的像素也会被丢弃。
- 手动修改GPU插值得到的深度
- 开启Alpha Blend
- 开启Alpha Blend的物体一般不会开启深度写入ZWrite off
- 关闭深度测试Depth Test
- 开启Multi-Sampling:多重采样会影响周边像素,而EarlyZ无法得知周边像素是否被裁剪,无法提前剔除
- 以及其他任何导致需要混合后面颜色的操作
- 开启ALpha Test或Clip/discard等手动丢弃片元操作
导致深度数据冲突
为了最大利用EarlyZ按照从近到远顺序渲染,但CPU阶段排序耗时,且严格按照从近到远渲染不能同时搭配合批优化手段
参考资料
[1] https://www.bilibili.com/video/BV1FK4y1u7iw
【技术美术百人计划】图形 3.5 Early-z和Z-prepass
[2] https://www.bilibili.com/video/BV1aM4y1g75f
【技术美术百人计划】图形 2.7.2 GPU硬件架构概述