在之前的章节里,我们知道的都是平面上的渲染,直接往屏幕上画东西就可以了,绘制的内容都比较单一。但在 3D 游戏里,我们需要考虑的东西则会多很多。比如在人群中,视野方向的人物模型很多,每一个人物模型都需要绘制,如何让距离相机进的物体不被离得远的遮挡?再比如,街道两边有很多带有玻璃窗的商店,如何通过玻璃窗看到里面的景象?
要实现这里的功能,就需要涉及到渲染流程的最后一个阶段:alpha 测试与混合。在这个阶段里 GPU 主要的工作是逐片元操作,将它们的颜色以某种形式合并,得到最终在屏幕上显示的像素颜色。主要涉及的工作有两个:对片元进行测试并进行合并。测试步骤决定了片元最终会不会被显示出来。在 WebGL 里主要的测试有裁剪测试、透明度测试、模板测试以及深度测试,这几个测试都是高度可配置的。其中,考量到裁剪测试没有模板测试来得更加灵活,因此本次就不涉及裁剪测试内容。整个测试流程如下图:
从图中可以看出,片元着色器输出的颜色缓冲并不是最终屏幕上呈现的颜色缓冲,还必须经过模板、深度和混合测试影响后才能得到最终用来输出的颜色缓冲。本章重点介绍模板测试和深度测试,混合测试将在下一章中为大家介绍。
>注意:由于这部分内容是补充知识,重点在于了解一下这部分的概念以及在 Cocos Creator 3.x 中的应用即可。
模板测试(Stencil Test)
Stencil 的本质是镂空,通过这样的板子就可以方便的画出某个特定的形状。模板测试的核心是持有一个模板缓冲,每个像素/片段都有一个模板值,通常每个模板值是 8 位(用掩码表示),也就是可以有 256 种不同的值,这样就可以通过设置我们想要的模板值来丢弃或保留这个片段。一个简单模板测试例子如下:
图片摘自 OpenGL
通常,用户在启用模板缓冲的时候,会将整个模板缓冲中的所有片段的模板值设置为 0,丢弃所有片段。然后再设置特定区域的模板值(大于 0)以及比较函数。GPU 会读取用户设置的模板值,然后将该值与模板缓冲中该位置的模板值按比较函数进行比较,最终决定是保留还是舍弃该片段,形成镂空,也就是遮罩效果。在模板测试中,有两个很重要的方法是 “stencilFunc” 和 “stencilOp”,前者用来控制 stencil 的测试方式,得出测试结果,后者根据结果决定要如何处理缓冲中的数据。
`void stencilFunc(GLenum func, GLint ref, GLuint mask)` :
func:指定模板测试比较函数。默认是 Always。
ref:用来做模板测试的参考值。
mask:指定操作掩码。在测试时会先将 ref 与 mask 进行与运算,再将 ref 与模板缓冲(stencil buffer)中的值进行与运算,最后根据比较函数得出结果。
单纯看这些描述可能还不是很理解这里的意思,