如何让模板缓冲仅在网格绘制区域生成遮罩?
问题描述
我尝试用模板缓冲(Stencil Buffer)给Sprite添加遮罩,未开启透明效果时功能正常,但添加透明后,遮罩会作用于整个纹理——我希望它仅在Quad网格的绘制区域生效。
(注:黑色Sprite是需要被遮罩的对象,能看到作为遮罩的Quad没有对纹理的透明区域进行遮罩,我只把Unity默认Quad网格传入了Mesh Filter。)
请问这是正常行为吗?有没有办法让遮罩仅在Quad的绘制区域生效?
遮罩Shader原代码
Tags { "RenderType" = "Transparent" } Pass { Stencil { Ref 1 Comp Always Pass Replace } ColorMask 0 // Don't write to any colour channels ZWrite Off // Don't write to the Depth buffer }
遮罩交互Shader原代码
Tags { "RenderType" = "Transparent" "Queue" = "Transparent" } Pass { Name "Sprite Lit" Tags { "LightMode" = "Universal2D" } // Render State Stencil { Ref 1 Comp Equal } Blend SrcAlpha OneMinusSrcAlpha, One OneMinusSrcAlpha Cull Off ZTest LEqual ZWrite Off }
解决方案
这是正常现象——你的遮罩Shader没有过滤透明像素,导致Quad的整个矩形区域都写入了模板缓冲,包括透明部分,所以Sprite的透明区域也会被遮罩规则影响。要让遮罩只作用于Quad的实际绘制区域,需要给遮罩Shader加上Alpha过滤逻辑。
修改后的遮罩Shader(Alpha测试版本)
Tags { "RenderType" = "TransparentCutout" } Pass { Stencil { Ref 1 Comp Always Pass Replace } ColorMask 0 // 不写入任何颜色通道 ZWrite Off // 不写入深度缓冲 AlphaTest Greater 0.5 // 只保留Alpha值大于0.5的像素,透明部分不会写入模板缓冲 }
关键改动说明
- 把
RenderType改成TransparentCutout,对应带Alpha裁剪的渲染类型,让管线正确处理透明过滤 - 添加
AlphaTest Greater 0.5指令:只有Alpha值超过阈值的像素才会执行模板缓冲的写入,Quad的透明区域就不会在模板缓冲中留下标记
如果用的是URP 2D管线,也可以用更现代的AlphaToMask替代AlphaTest,效果一致:
Tags { "RenderType" = "TransparentCutout" } Pass { Stencil { Ref 1 Comp Always Pass Replace } ColorMask 0 ZWrite Off AlphaToMask On // 启用Alpha转遮罩,自动过滤透明像素 }
修改后,遮罩就只会在Quad的非透明绘制区域生效,Sprite的透明部分不会再被错误遮罩。
内容的提问来源于stack exchange,提问作者Hemessfell
相关产品推荐
相关产品推荐

