先看最终的效果图:
美术提了一个在按钮上加粒子特效的需求,因此需要做下裁剪的功能,防止粒子特效超框(如上图)。一开始想的是用之前的方法,给shader一个按钮位置以及长宽的Vector,计算按钮区域来计算遮挡。但是发现那个按钮的图片是一个梯形的(如图),空白的部分也不能出现粒子,这就麻烦了。
后来查了下发现shader有一个Stencil的功能,叫做模板缓存,可以实现我们想要的需求(不过似乎比较耗费性能)。这个也是Mask组件的实现原理,不过mask可以遮挡UI组件,对粒子无法产生效果。因此需要我们自己来处理下。
github:https://github.com/luckyWjr/Demo
UGUI自带的Mask功能
首先先来看看UGUI的Mask功能,首先创建一个Image,取名ImageMak,用于放遮挡的图片,然后我们再创建一个Image作为其子控件,用于放需要被遮挡的图片,如图:
然后我们在ImageMask上添加Mask组件即可,即可实现遮挡的效果。你会发现两个Image的UI/Default Shader的几个Sentcil参数发生了变化,这也是我们后面要重点讲的。
Show Mask Graphic:决定是否显示作为Mask的Image。原理是将Shader中的ColorMask的值设为0,即不输出颜色。
Sentcil
这一篇,我们首先具体讲讲Sentcil的一些属性,由于内容较多具体的内容实现留到下一篇再详细讲解。
官方文档链接:https://docs.unity3d.com/Manual/SL-Stencil.html
Sentcil,模板缓存可以用于实现每像素的保存或丢弃。
SubShader {
Stencil {
Ref 1
Comp Always
Pass Replace
ReadMask 255
WriteMask 255
Fail Keep
ZFail Replace
}
}
对应参数的含义:
假设当前像素缓存的值为stencilBufferValue,即为缓存中ref的值
参数 | 值 | 默认值 | 含义 |
Ref |
0-255 | 0 | 设定参考值 referenceValue |
Comp | CompareFunction | Always | 比较方法,即拿 referenceValue 和 stencilBufferValue 进行比较 |
Pass | StencilOp | keep | 当模板测试和深度测试都通过时,进行的处理操作 |
ReadMask | 0-255 | 255 | 读取的时候将该值 maskValue 与 referenceValue 和 stencilBufferValue 分别进行 |