zoukankan      html  css  js  c++  java
  • (九)Mask详解

    1.前言

    本文从逻辑和原理上详细分析Ugui的Mask组件。Mask组件的逻辑没有RectMask2D复杂,但是原理稍微麻烦一点,用得到渲染的模板检测。

    2.模板遮罩原理

    2.1 模板值

    以下图为例,假如均没有开启模板检测,canvas上只有一个RawImage组件,那么整个背景模板值为0。如果图中RawImage开启模板检测,并设置模板检测值为2(模板检测参考值是自定义的)。那么图片区域模板值为2,以外红色区域为0(模板值是以像素为单位进行设置的),如果开启根据透明通道值设置(Use Alpha Clip为true),则RawImage非透明区域为2,其他区域为0。
    在这里插入图片描述

    2.2 模板参数设置

    模板值通过shader中设置相关变量实现的,我们通过ui默认的shader来解释。新建Material,并设置shader为UI/default,并赋值给一个RawImage,则可以看到参数面板如下,则可进行相关参数设置:
    在这里插入图片描述
    我们来解释一下参数及其意义:

    Stencil ID:设置的模板参考值,如图设置为2

    Stencil Operation:模板值操作方式,即如何进行操作,如果如图设置为2。则表示replace,即用Stencil ID的值代替此ui覆盖区域的像素的模板值。参考值如下所示:

    namespace UnityEngine.Rendering
    {
        public enum StencilOp
        {
            Keep = 0,//保持原值
            Zero = 1,//设置为0
            Replace = 2,//用当本参考值代替原值
            IncrementSaturate = 3,//逐次增加,当超过255时保持255
            DecrementSaturate = 4,//逐次减小,当少于0时保持0
            Invert = 5,//按位取反
            IncrementWrap = 6,//逐次增加,当超过255时继续从0开始
            DecrementWrap = 7//逐次减小,当少于0时继续从255开始
        }
    }
    

    Stencil Comparison:比较方法,参考值如下,如果设置为3(即equal),则表示如果当前RawImage渲染时,模板值如果与之前模板值相同(即通过模板测试)则渲染当前RawImage像素,反之舍弃。

    namespace UnityEngine.Rendering
    {
        public enum CompareFunction
        {
            Disabled = 0,//不进行深度和模板检测
            Never = 1,//模板和深度检测均不通过
            Less = 2,//小于前模板值时通过检测
            Equal = 3,//等于前模板值时通过检测
            LessEqual = 4,//小于等于前模板值时通过检测
            Greater = 5,//大于前模板值时通过检测
            NotEqual = 6,//不等于前模板值时通过检测
            GreaterEqual = 7,//大于等于前模板值时通过检测
            Always = 8//一直通过检测,与1相反
        }
    }
    

    Stencil Read/Write Mask:即读取或者重新写入模板值时的Mask,即与填写的值按位与进行计算。如果255则表示值不变,即取出/写入多少就是多少。

    Color Mask:表示写入颜色值时写入的成分。如下所示:

    namespace UnityEngine.Rendering
    {
        [Flags]
        public enum ColorWriteMask
        {
            Alpha = 1,
            Blue = 2,
            Green = 4,
            Red = 8,
            All = 15
        }
    }
    

    Use Alpha Clip:是否进行根据通道值剔除,如果开启则会按像素进行处理,否则按Rect形状进行模板值操作。

    2.3 模板参数使用

    模板测试分两步进行,即模板值测试与模板值设置。

    2.3.1 模板测试

    用StecilBufferValue来代替模板缓冲值,则如果满足(Stencil ID&Read Mask) StencilComparison (StencilBufferValue&Read Mask)则表示通过测试,即当前像素可以写入FrameBuffer(若不理解可认为是写到屏幕上)。否则抛弃像素。

    2.3.2 模板设置

    如果Stencil Operation值为Replace,则表示设置当前像素位置的模板值为Stencil ID,如果为IncrementSaturate,则表示再当前卖报纸的基础上加1,如果超过255,则保持255。模板测试之后,无论模板测试通过与否,都要对模板进行相应的更新

    2.4 模板测试应用

    假如在上一张图片的基础上再加一张图片,且这两张均未开启模板检测,则显示结果如下。因为渲染顺序问题,则蓝色路飞头像会遮挡前面山水图。
    在这里插入图片描述

    然后设置山水图模板参数如下所示:
    在这里插入图片描述
    如上图片所示,我们开启模板检测,并设置山水图模板值为2。StencilComparision值为8,表示直接通过模板测试。则将此图片像素信息全部写入缓冲区(因为ColoMask值为15)。由于StencilOperation值为2(替换),则将StencilID值写入覆盖区域。对第二张蓝色路飞图开启模板检测,设置模板参数如下图所示。由于其StencilComparision参数为3,则表示若前后模板值相等即均为2,则通过测试保留像素值,否则丢弃此像素值。同时保持模板值不变,即原来是2的区域还是2,是0的区域还是0。
    在这里插入图片描述效果如如下所示:
    在这里插入图片描述
    如果将第二张图片StencilComparision为5,即如果大于模板值则保留像素,那么第一章图片区域的像素就会被舍弃,而其他区域会被保留,效果类似于挖洞,如下所示:
    在这里插入图片描述

    3.Mask逻辑

    上述为Mask的实现原理,至于子物体全部遮罩则是逻辑设置参数实现的。流程如下:
    1)Mask启动时通知所有子游戏物体,可以进行进行模板值重新计算(m_ShouldRecalculateStencil标记为true)。
    2)Graphic进行渲染时会设置材质,会调用如下属性,会查找所有IMaterialModifier,修改模板值。

            public virtual Material materialForRendering
            {
                get
                {
                    var components = ListPool<Component>.Get();
                    GetComponents(typeof(IMaterialModifier), components);
    
                    var currentMat = material;
                    for (var i = 0; i < components.Count; i++)
                        currentMat = (components[i] as IMaterialModifier).GetModifiedMaterial(currentMat);
                    ListPool<Component>.Release(components);
                    return currentMat;
                }
            }
    

    3)由于Mask和MaskableGraphic均继承实现接口IMaterialModifier,所以根据层级设置相关模板参数,从而实现子物体遮罩想过。

    4.结语

    以上为Mask的基本原理与基本逻辑

  • 相关阅读:
    MNIST手写字母识别(二)
    MNIST手写字母识别(一)
    多元线性回归问题(Tensorflow 求解)
    单变量线性回归问题(TensorFlow实战)
    TensorBoard可视化初步
    TensorFlow的基本运算
    NumPy科学计算库
    tensorflow使用Session模块时报错:AttributeError: module 'tensorflow' has no attribute 'Session',已解决
    Python 第一个爬虫
    Python(列表)
  • 原文地址:https://www.cnblogs.com/llstart-new0201/p/12681277.html
Copyright © 2011-2022 走看看