编辑注:Stencil Buffer 相关文章站内其实有文章和日志涉及到过。比如较为大家关注的《笼中窥梦(Moncage)》采访时就有提到(笼中窥梦@indienova)。这一次作者阿创投稿的系列文章将带大家了解更多相关的知识。
模板测试(Stencil Test)是现代渲染流水线的一环,其中涉及到的就是模板缓冲(Stencil Buffer),模板缓冲可以用来制作物体的遮罩、轮廓描边、阴影、遮挡显示等等效果,本章将带你了解什么是模板缓冲和模板测试。
一、模板缓冲是什么?
对现代渲染流水线有过了解的同学,一定知道深度测试(Depth Test)吧,深度测试可以从一个特定角度达到最近物体的排序的效果,与之相关的深度缓冲(Depth Buffer)里的值始终保存离摄像机最近物体的深度值(透明物体除外),这样就可以从前往后绘制物体了,避免了很多的 overdraw,大大提高了渲染性能,是渲染流水线不可或缺的一环。
但在深度测试之前还有一个测试,就是模板测试(Stencil Test),其知名度远远不及深度测试,有很多同学都只是偶尔听过一两下,不知道是什么东西,有啥用(就是之前的我了……)
下面就由我来带大家了解一下吧~
要想了解什么是模板测试,首先需要了解什么是模板缓冲(Stencil Buffer)。
其实和深度缓冲类似。模板缓冲也可以为屏幕上的每一个像素进行保存一个 8
位的无符号整数,即范围 0~255
的整数;
在 Unity 中,我们可以将这些模板值设置为我们想要的值,然后在随后渲染结果 Pass 与其进行比对,根据比对结果,我们就可以选择丢弃或是保留这个像素。此过程发生在渲染流水线的合并阶段中,具体在片元着色器之后,深度测试之前,被称为模板测试(Stencil Test)。
通俗的来说,模板测试就像上图我们用的喷漆涂鸦一样。 我们首先准备一张中间镂空形状为 T 的纸板,还有一张空白底板。 当我们拿喷漆喷在镂空纸板上,结果只有镂空的部分喷漆才能通过。这样就在空白底板印上了 T 字图案。
以上喷漆其实就对应了我们每一个像素的颜色,而镂空纸板对应就是模板(测试),最后空白底板就对应了最终显示在我们眼前的屏幕。
我猜这就是 Stencil Buffer 名字的由来吧……
二、Unity 中的语法
1. Stencil 常见语法格式
Stencil{ Ref referenceValue // 参考值 默认值为 0 Comp comparisonFunction // 定义参考值与缓冲值比较的方法 默认值为 Always Pass stencilOperation // 定义当通过模板测试时,根据参考值对缓冲值的处理方法 默认值为 keep Fail stencilOperation // 定义当没有通过模板测试时,根据参考值对缓冲值的处理方法 默认为 keep ZFail stencilOperation // 定义当通过模板测试却没有通过深度测试时,根据参考值对缓冲值的处理方法 默认为 keep }
举个实际例子
Stencil{ Ref 1 Comp Equal Pass Keep }
上述代码的意思是: 我们自己设定了 Ref 参考值为 1
。渲染 Pass 得到像素颜色后,拿参考值 1
与模板缓冲中此像素位置的缓冲值比对,只有 Equal 相等才算通过,并且 Keep 保持原有缓冲值,否则丢弃此像素颜色。
三、后续安排
通过本章,相信大家已经了解了什么是模板缓冲了。也简单了介绍其在 Unity ShaderLab 中的语法。
后续几章将介绍在实际开发中,运用模板缓冲达到效果实现(应该不会咕咕咕吧,作业不多的话……)
我也可能没讲清楚哈哈哈,大家有啥不懂也积极评论交流嘛,大家一起学习进步~
参考资料
- OpenGL 模板缓冲区的理解:
https://www.jianshu.com/p/89c2454bcd26 - UnityShader 实例 09:Stencil Buffer & Stencil Test:
https://blog.csdn.net/u011047171/article/details/46928463 - 模板测试:
https://learnopengl-cn.github.io/04%20Advanced%20OpenGL/02%20Stencil%20testing/
下一章预告
运用 Stencil Buffer 实现的轮廓描边:
起点有点高