模板测试 Stencil testing
渲染管线的流程:应用阶段 -> 几何阶段 -> 光栅阶段
参考:Unity渲染流水线 - 知乎 (zhihu.com)
参考:Unity3D Stencil Test模板测试详解-腾讯游戏学堂 (qq.com)
模板测试发生在光栅阶段,顺序是:Alpha测试 -> 模板测试 -> 深度测试
Unity官方文档,模板测试语法:
https://docs.unity3d.com/cn/2018.4/Manual/SL-Stencil.html
1.我们的GPU中有一个模板缓冲区(Stencil Buffer),其大小为整个屏幕大小*8位,即屏幕上的每一个像素点都存储有一个模板值,该模板值是8位的,所以其值范围为0~255
2.如果我们在Shader中开启了模板测试,要渲染某个像素的时候,就会读取读取Shader中设置的参考值Ref(我们按需求设置),同时模板缓冲区中该像素对应的模板值StencilValueInBuffer,如果参考值Ref与模板缓冲区中的值StencilValueInBuffer满足某个条件(此条件是我们在Shader中按我们的需求指定的),则测试通过,该像素可以渲染;如果不满足,则该像素不可以渲染。无论深度测试是否通过,Shader中都有权利向模板缓冲区写入模板值(前提是开启了模板测试)
实例:
参考:Unity3D Shader系列之模板测试 - 知乎 (zhihu.com)
比如想实现以下效果,绿色片面在前面,红色面片在后面,只绘制绿色跟红色重叠的部分,并且显示的是红色的像素
1.因为想实现绿色面片影响红色,所以绿色必须先渲染,红色再渲染。因此绿色的Z轴,或者渲染队列要比红色的优先。
2.因为我们不想显示绿色的面片,所以可以把绿色的ColorMask关闭,ColorMask 0表示该Shader会正常执行逻辑,只是不渲染出来而已。深度缓冲、模板缓冲会照常写入。
3.因为绿色在前面,Z轴比红色的高,而我们又想画出红绿相交的部分,所以要把绿色的深入写入关闭(ZWrite off),否则被绿色面片挡住的红色部分因为深度检测不通过根本不会渲染
4.绿色面片开启模板测试,并且在每个像素的地方写入模板缓冲值(例如1)
5.等到红色的执行逻辑的时候,会判断每个像素点上对应的模板缓冲值,如果与之前绿色面片写入的一致,证明该区域是绿色覆盖的区域,就让它模板测试通过,画出像素
绿色面片的Shader:
Stencil { Ref [1] // 模板测试参考值为1 Comp Always // 与模板缓冲区对比测试,无论任何情况,都通过 Pass Replace // 模板测试通过后,往缓冲区里写入参考值1 } ZWrite Off // 关闭深入检测,防止挡住了红色面片导致红色的逻辑不执行 ColorMask 0 // 因为不想看到绿色的面片,直接关闭颜色就行了
红色面片的Shader:
Stencil
{
Ref [1] // 模板测试参考值为1
Comp Equal // 只有参考值与该像素对应的模板缓存区里的值一直的时候,才算测试通过,把像素渲染出来
Pass IncrSat // 测试通过后,把模板缓冲区里的值+1(用意不明)
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· spring官宣接入deepseek,真的太香了~