写在最前:
1.工程环境:Unity 2017。
2.UI插件:UGUI。
3.本文章是个人的学习记录贴,如果有幸被翻阅,请不要吐槽排版。
先摘录一下 UI/Default 的相关关键代码,以下描述会用到(本人自己创建了一个Shader,并复制了UI/Default源码,所以可以更改!)
#pragma multi_compile __ UNITY_UI_CLIP_RECT //------------------------------------- a
#pragma multi_compile __ UNITY_UI_ALPHACLIP //------------------------------------- b
#ifdef UNITY_UI_CLIP_RECT
color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect); //----------------c
#endif
#ifdef UNITY_UI_ALPHACLIP
clip(color.a - 0.001); //------------------d
#endif
正文:
1.Mask:
①.Mask原理是使用的模板缓冲区,来实现遮罩的功能。在绘制Mask下子物体时,与模板缓冲区的值进行比对来实现的裁剪效果,所以这种裁剪效果可以针对3D物体的。
②.实测表明 Mask与Image必须挂在同一GameObject下,否则Mask将失效。个人推测是如果没有Image组件,Mask将无法正确对模板缓冲区写入值,抑或是压根就不会去写入。
③.实测会发现,哪怕注释掉上面的 c,d行的代码,Mask依然会正常运作,这更加说明了,Mask的原理是模板缓冲。
④.实测发现,Mask会激活 UNITY_UI_CLIP_RECT 关键字 ,相关证据没有找到,但是表现出来的现象是这样。
2.RectMask2D:
①.RectMask2D针对2D同平面物体做裁剪,不会产生额外DC。
②.RectMask2D会有不完全裁剪的Bug,那种露一半的物体会不被裁剪,可能原因见下一条。
③.RectMask2D貌似不会激活 UNITY_UI_CLIP_RECT 关键字。
④.使用默认的UI/Default 去渲染Image发现可以被裁剪,复制粘贴官方的源码该下Shader名字发现无法被裁剪,真心坑爹,可能的原因参见第二条,深层原因暂不知道。
⑤.如果修改a行代码,将 __ 去掉,发现是可以正确裁剪的,让我更加相信是UNITY_UI_CLIP_RECT没有被激活,同样还是那个问题,为啥 Unity默认的Shader被激活了这个关键字,而我复制粘贴的代码缺没激活,可恶!
简单总结:
1.简单的2D UI,如果使用到了ScrollRect组件,那么下面的遮罩组件可以用RectMask2D,这样不用写优化逻辑DC就会低很多。如果相关优化逻辑写的好,当然用什么都无所谓。
2.如果涉及对3D物体进行遮罩,必须使用Mask + Image 的组合,当然你用Unity的选项创建的话,Unity会自动帮你创建好。但是这种涉及模板缓冲的功能比较消耗性能。
3.表面上看到UI/Default 里面有相关像素裁剪代码(c,d行的代码),但是会发现,哪怕你注释掉了,无论是Mask还是RectMask2D,都能对完全超出视野的元素有裁剪功能,只不过RectMask2D会有不完全裁剪的Bug。
4.如果你使用到了自己写的Shader遇到了相关裁剪的bug,可以尝试将 a 代码的 __ 去掉,或者 将 c 代码的 #ifdef条件注释掉。