欢迎光临散文网 会员登陆 & 注册

【技术美术百人计划】模板测试与深度测试

2023-06-22 15:44 作者:柴郡笔记  | 我要投稿

模板测试概览:

图1为颜色缓冲区

图2为模板缓冲区,默认为0,给每个片元分配一个[0,255]之间的数值,8位。

图3为通过自定义准则得到的结果。为0则不渲染,为1则渲染。


模板测试在渲染管线的位置:

Stencil Test

Pixel Ownership Test:控制像素的使用权限。(只能在game窗口和scene窗口显示。其他位置都会被剔除掉)

Scissor Test:裁剪测试。(在game和scene窗口内,自己可以再次定义渲染范围)

Alpha Test:透明度测试。(设置一个透明度阈值,大于这个阈值就通过测试,相反小于就剔除)

Stencil Test:模板测试

Depth Test:深度测试

Blending:透明度混合


模板测试书面理解:

模板缓冲区可以为屏幕上的每一个像素点保留一个无符号的整数值(通常是8位整数)。

在渲染中,可以用这个值与一个预先设定的参考值相比较,根据比较结果来决定是否更新相应颜色点的值,这个过程被称为模板测试。

模板测试发生在透明度测试后,深度测试前,如果模板测试通过,则更新像素值,反之则不更新。


模板测试语法:


比较操作ComparisonFunction


更新值(stencilOperation)


模板测试总结

  • 使用模板缓冲区最重要的两个值:当前模板缓冲值(stencilBufferValue)和模板参考值(referenceValue)。

  • 模板测试主要就是对这两个值使用特定的比较操作:Never,Always,Less,LEqual,Greater,GEqual,Equal。

  • 模板测试之后要对模板缓冲区的值(stencilBufferValue)进行更新操作,更新操作包括:Keep,Zero,Replace,IncrSat,DecrSat,Invert等等。

  • 模板测试之后可以根据结果对模板缓冲区做不同的更新操作,比如模板测试成功操作Pass,模板测试失败操作Fail,深度测试失败操作ZFail,还有正对正面和背面精确更新操作PassBack,PassFront,FailBack等等。




深度测试(Z Test)

深度测试判断物体前后遮挡关系
深度测试在模板测试后透明度混合前

深度测试是什么:

所谓深度测试,针对当前对象在屏幕上(frame buffer)对应的像素点,将对像自身的深度值与当前该像素点缓存的深度值作比较,通过则写入颜色缓冲,否则不写入。

发展理解上的深度测试

深度缓冲区

深度缓冲就像颜色缓冲一样,在每个片段储存信息,和颜色缓冲有着一样的宽度和高度。深度缓冲是由窗口系统自动创建的,他会以16、24、32位float的形式储存深度值。大部分系统中,其精度都是24位的。

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

通过ZWrite和ZTest调用ZBuffer(深度缓冲区)实现相应的效果。


ZWrite(深度写入)

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

当我们开启深度写入时,物体被渲染到屏幕上时,每个像素的深度都写入到深度缓冲区中;反之,则不会写入到深度缓冲中。但是,物体是否被写入深度缓冲,除了ZWrite外,更重要的是ZTest(深度测试)通过,如果ZTest都没通过,那也就不会写入深度了。


ZTest(深度测试)

ZTest分为通过和不通过两种状态,加上ZWrite就是4种状态。

  • 深度测试 On,深度写入 On:写入深度缓冲区,写入颜色缓冲区。

  • 深度测试 On,深度写入 Off:不写入深度缓冲区,写入颜色缓冲区。

  • 深度测试 Off,深度写入 On:不写入深度缓冲区,不写入颜色缓冲区。

  • 深度测试 Off,深度写入 Off:不写入深度缓冲区,不写入颜色缓冲区。

ZTest比较操作


渲染队列

unity有几种内置的渲染队列,从先到后,数字越小越先渲染。

使用方法:

不透明物体渲染顺序:从前到后

透明物体渲染顺序:从后到前


Early-Z

传统渲染管线中,ZTest处于Blending阶段,这时会进行深度测试,所有对象的像素着色器都会计算一遍,会造成大量无用计算,每个像素点会重叠很多计算。

因此,现代GPU运用了Early-Z的技术,在顶点着色器和片元着色器之间进行一次深度测试,如果失败,则不必进行片元计算,提升性能。但是最终ZTest仍要进行,以保证计算遮挡结果的正确。

前面的一次Z-Cull是为了裁剪以达到优化目的,后一次主要是Z-Check,为了检查,如下图:


深度值

  • 世界坐标的Z分量

  • 观察空间的Z分量(线性深度)

  • 准备投影,深度缓冲中存储Z/W分量(透视投影非线性)

https://learnopengl-cn.readthedocs.io/zh/latest/04%20Advanced%20OpenGL/01%20Depth%20testing/

深度值

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

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


Fdepth%3D%5Cfrac%7B1%2Fz%E2%88%921%2Fnear%7D%7B1%2Ffar%E2%88%921%2Fnear%7D


深度冲突

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


解决方法

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

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

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


深度测试总结

  • 使用深度缓冲区最重要的两个值:当前深度缓冲区值(ZBufferValue)和深度参考值(referenceValue),并通过比较操作获取理想渲染效果。

  • Unity中的渲染顺序:先渲染不透明物体,顺序是从前到后;在渲染透明物体,顺序是从后到前。

  • 通过ZWrite和ZTest组合使用控制半透明物体的渲染。

  • 引入Early-Z技术后的深度测试相关的渲染流程。

  • 深度缓冲区中储存的深度值为0-1范围的浮点数,且为非线性,大多数精度都是24位。


【技术美术百人计划】模板测试与深度测试的评论 (共 条)

分享到微博请遵守国家法律