HPP_Graphics_2.7 模板测试和深度测试

a). 模板测试

  • 处于逐片元操作

模板测试00

模板测试01

模板测试02

a.1). Unity 中的模板测试

  • 语法表示

    Unity_stencil

    Unity_stencil_Comparison

    Unity_stencil_Update

  • 可作为遮罩等操作

    StencilBufferValue

a.2). 作业:Unity中实现的效果

StencilTest_Unity


【链接补充】

[1]. https://blog.csdn.net/u011047171/article/details/46928463

[2]. https://blog.csdn.net/liu_if_else/article/details/86316361

[3]. https://gameinstitute.qq.com/community/detail/127404

[4]. https://learnopenglcn.readthedocs.io/zh/latest/04%20Advanced%20OpenGL/02%20Stencil%20testing/

[5]. https://www.patreon.com/posts/14832618

[6]. https://www.udemy.com/course/unity-shaders/

b). 深度测试

ZTest

  • 模板测试后,透明度混合前

Z-Buffer

Z_Buffer

Z Write

深度写入包括两种状态:ZWrite On 与 ZWrite Off

当我们开启深度写入的时候,物体被渲染时针对物体在屏幕(更准确地说是frame buffer)上每个像素的深度都写入到深度缓冲区;反之,如果是ZWrite Off,那么物体的深度就不会写入深度缓冲区。但是,物体是否会写入深度,除了ZWrite这个状态之外,更重要的是需要深度测试通过,也就是ZTest通过,如果ZTest都没通过,那么也就不会写入深度了。

ZTest分为通过和不通过两种情况,ZWrite分为开启和关闭两种情况的四种情况:

  • 深度测试通过,深度写入开启:写入深度缓冲区,写入颜色缓冲区。
  • 深度测试通过,深度写入关闭:不写深度缓冲区,写入颜色缓冲区。
  • 深度测试失败,深度写入开启:不写深度缓冲区,不写颜色缓冲区。
  • 深度测试失败,深度写入关闭:不写深度缓冲区,不屑颜色缓冲区。

Z Test比较操作

Z_Comp

渲染队列

Unity中内置的几种渲染队列,按照渲染顺序,从先到后进行排序,队列数越小,越先渲染,队列数越大,越后渲染。

  • Background(1000) :最早被渲染的物体的队列。
  • Geometry(2000) :不透明物体的渲染队列。大多数物体都应该使用该队列进行渲染,也是Unity Shader中默认的渲染队列。
  • AlphaTest(2450) :有透明通道,需要进行Alpha Test的物体的队列,比在Geometry中更有效。
  • Transparent(3000) : 半透物体的渲染队列。一般是不写深度的物体,Alpha Blend等的在该队列渲染。
  • Overlay(4000) :最后被渲染的物体的队列,一般是覆盖效果,比如镜头光晕,屏幕贴片之类的。

Unity中设置渲染队列

1
2
3
4
//默认是Geometry
Tags{
"Queue" = "Transparent"
}
  • 不透明物体的渲染顺序:从前往后。
  • 透明物体的渲染顺序:从后往前。(OverDraw)
  • 对于使用了多个Pass的物体,其渲染队列会设置为Pass中的最小值(如两个Pass中一个是Geometry(2000),另一个是Transparent(3000),那该物体会按Geometry的队列渲染,然后按Shader中从上到下执行Pass)。

Early-Z

传统的渲染管线中,ZTest其实是在Blending阶段,这时候进行深度测试,所有对象的像素着色器都会计算一遍,没有什么性能提升,仅仅是为了得出正确的遮挡结果,会造成大量的无用计算,因为每个像素点上肯定重叠了很多计算。因此现代GPU中运用了Early-Z的技术,在Vertex阶段和Fragment阶段之间(光栅化之后,fragment之前)进行一次深度测试,如果深度测试失败,就不必进行fragment阶段的计算了,因此在性能上会有很大的提升。但是最终的ZTest仍然需要进行,以保证最终的遮挡关系结果正确。前面的一次主要是Z-Cull为了裁剪以达到优化的目的,后一次主要是Z-Check,为了检查,如下图:

EarlyZ

c). 深度值

Deepth

为什么深度缓冲区存储非线性深度呢?

正确的投影特性的非线性深度方程是和1/z成正比的,这样基本上做的是在Z很近的时候是高精度和Z很远的时候是底精度。这样就是模拟了人眼观察,近处的物体很清晰,而远处的物体很模糊。(和现在还用伽马校正的原因类似)

Z-fighting

两个平面或三角形很紧密相互平行,深度缓冲区不具有足够的精度以至于无法得到哪一个靠前。导致了着两个形状不断切换顺序出现怪异问题。这被称为深度冲突(Z-fighting),因为它看上去像形状争夺顶靠前的位置。(UE中重叠闪来闪去的那个)

  • 解决方法

    • 让物体之间不要离得太近。

    • 尽可能把近平面设置得远一些。

    • 放弃一部分性能来获得更高精度的深度值。

    • Z-Offset

Z_F