Unity Mask 和RectMask2D原理和区别

原理

Mask

1.Mask会赋予Image一个特殊的材质(GetModiferMaterial),这个材质会给Image的每个像素点进行标记,将标记结果存放在一个模板缓存内(这个缓存叫做 Stencil Buffer)
2. 当子级UI进行渲染的时候会去检查这个 Stencil Buffer内的标记,如果当前覆盖的区域存在标记(即该区域在Image的覆盖范围内),进行渲染,否则不渲染

RectMask2D

1.C#层:找出父物体中所有RectMask2D覆盖区域的交集(FindCullAndClipWorldRect)
2.C#层:所有继承MaskGraphic的子物体组件调用方法设置剪裁区域(SetClipRect)传递给Shader
3.Shader层:接收到矩形区域_ClipRect,片元着色器中判断像素是否在矩形区域内,不在则透明度设置为0(UnityGet2DClipping )
4.Shader层:丢弃掉alpha小于0.001的元素(clip (color.a - 0.001))

Mask源码解析

首先 Mask调用 MaskUtilities.NotifyStencilStateChanged(this);
去通知所有继承IMaskable 接口的组件去计算Mask绘制
就是调用 IMaskable.RecalculateMasking() 方法
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

StencilMaterial 就是一个动态修改 和自定义Material 的工具类

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

RectMask2D 源码解析

RectMask2D 实现了IClipper 接口 PerformClipping 函数 可以用来接待剪裁画布回调的一部分更新循环。
子节点的Image 实现了 IClippable 接口 裁剪接口

在这里插入图片描述
调用 MaskUtilities.Notify2DMaskStateChanged() 遍历所有子节点
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
触发OnCullingChanged 最后在画布Rebuild 的时候触发
Canvas.willRenderCanvases() 调用PerformUpdate

在这里插入图片描述
PerformUpdate 函数触发Cull
在这里插入图片描述
在调用Cull裁剪函数后 触发Mask2D.cs 里的 PerformClipping
在这里插入图片描述
在这里插入图片描述

设置完shader的裁剪区域 后调用 Cull函数 进行裁剪
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

总结一下

Mask 优缺点 多DrawCall 但多个Mask可合批

Mask 会多出两个DrawCall 一个是 Mask 本身 会创建一个材质球 把自身Image 的像素标记到模板缓冲区StencilBuff 导致一个DrawCall 另一个是 在Mask 遍历完所有子节点 修改子节点的材质球参数 赋值为对应的裁剪参数 最后 会重置一下缓存StencilBuff 导致又有一个DrawCall
在这里插入图片描述
多个Mask 直接 如果达成合批条件(不能重叠) 即 Mask组件本身的图片一样 他就能合批(即Mask首合批) 同理Mask尾部遍历完如果能合批 也会合批
但是 Mask首 无法与另一个Mask尾合批
多个Mask 里的 子节点如果能合批 也会合批
Mask节点可以作为子节点的BottonUI (即响应UI)

Mask2D 优缺点 没有额外DrawCall 但是 多个Mask2D里面的图是无法合批的

Mask2D 不依赖图片组件 本身组件不会产生额外DrawCall
但是他节点下的图片 不能跟节点外的进行合批 是分离的
多个Mask2D 之间也是不能合批的

猜你喜欢

转载自blog.csdn.net/qq_32756581/article/details/126510907