• Unity UI Mask实现原理 2019-04-16 22:21:08
    Unity UI Mask实现原理 Mask的实现思路: 与Image组件配合工作,根据Image的覆盖区域来定位显示范围,所有该Image的子级UI元素,超出此区域的部分会被隐藏(包括UI的交互事件) Mask的实现原理Mask会赋予Image...

    Unity UI Mask实现原理

    Mask的实现思路: 与Image组件配合工作,根据Image的覆盖区域来定位显示范围,所有该Image的子级UI元素,超出此区域的部分会被隐藏(包括UI的交互事件

    Mask的实现原理:

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

    UGUI自身实现的Mask组件实现遮罩,需要子级UI进行配合,Unity内置的UI组件继承自MaskableGraphic,该类是Mask的配合实现者:
    相关代码:

    	public virtual Material GetModifiedMaterial(Material baseMaterial)
    {
        var toUse = baseMaterial;
    
        if (m_ShouldRecalculateStencil)
        {
            var rootCanvas = MaskUtilities.FindRootSortOverrideCanvas(transform);
            m_StencilValue = maskable ? MaskUtilities.GetStencilDepth(transform, rootCanvas) : 0;
            m_ShouldRecalculateStencil = false;
        }
    
        // if we have a enabled Mask component then it will
        // generate the mask material. This is an optimisation
        // it adds some coupling between components though :(
        Mask maskComponent = GetComponent<Mask>();
        if (m_StencilValue > 0 && (maskComponent == null || !maskComponent.IsActive()))
        {
            var maskMat = StencilMaterial.Add(toUse, (1 << m_StencilValue) - 1, StencilOp.Keep, CompareFunction.Equal, ColorWriteMask.All, (1 << m_StencilValue) - 1, 0);
            StencilMaterial.Remove(m_MaskMaterial);
            m_MaskMaterial = maskMat;
            toUse = m_MaskMaterial;
        }
        return toUse;
    }   
    

    这里的核心代码是为UI生成一个材质:

    var maskMat = StencilMaterial.Add(toUse, (1 << m_StencilValue) - 1, StencilOp.Keep, CompareFunction.Equal, ColorWriteMask.All, (1 << m_StencilValue) - 1, 0);     
    

    这个材质在渲染时会去取StencilBuffer的值,并通过CompareFunction这个枚举变量所指定的比较方法进行比较,符合比较结果会进行渲染,否则不进行渲染。
    因此可以通过改写此方法中的比较方式,来达到类似挖孔的效果,即超出Image区域的显示,Image内的子UI不显示:

    public class HoleImage : Image {
    public override Material GetModifiedMaterial(Material baseMaterial)
    {
        var toUse = baseMaterial;
    
        if (m_ShouldRecalculateStencil)
        {
            var rootCanvas = MaskUtilities.FindRootSortOverrideCanvas(transform);
            m_StencilValue = maskable ? MaskUtilities.GetStencilDepth(transform, rootCanvas) : 0;
            m_ShouldRecalculateStencil = false;
        }
    
        // if we have a enabled Mask component then it will
        // generate the mask material. This is an optimisation
        // it adds some coupling between components though :(
        Mask maskComponent = GetComponent<Mask>();
        if (m_StencilValue > 0 && (maskComponent == null || !maskComponent.IsActive()))
        {
            var maskMat = StencilMaterial.Add(toUse, (1 << m_StencilValue) - 1, StencilOp.Keep, CompareFunction.NotEqual, ColorWriteMask.All, (1 << m_StencilValue) - 1, 0);
            StencilMaterial.Remove(m_MaskMaterial);
            m_MaskMaterial = maskMat;
            toUse = m_MaskMaterial;
        }
        return toUse;
    }
    }   
    

    将 CompareFunction.Equal 改为 CompareFunction.NotEqual 实现遮罩的反效果,挖孔。 参考: UnityGUI扩展实例:图片挖洞效果 Mask的反向实现

    修改 CompareFunction 的比较方式也可以通过 UI 材质中的参数值进行:

    UI材质的默认参数:

    Stencil Comparison:比较值
    Stencil ID:UI ID值
    Stencil Operation:缓冲区操作值
    Stencil Write Mask:遮罩写入
    Stencil Read Mask:遮罩读取

    在渲染时,将stencil buffer的值与ReadMask与运算,然后与Ref值进行Comp比较,结果为true时进行Pass操作,否则进行Fail操作,操作值写入stencil buffer前先与WriteMask与运算。
    在UI Shader中 参数(属性)值的对应设置:

    Ref [ _Stencil]
    Comp [ _StencilComp]
    Pass [ _StencilOp]
    ReadMask [ _StencilReadMask]
    WriteMask [ _StencilWriteMask]

    Ref
    用来设定参考值referenceValue,这个值将用来与模板缓冲中的值进行比较。referenceValue是一个取值范围位0-255的整数。
    Comp
    是定义参考值(referenceValue)与缓冲值(stencilBufferValue)比较的操作函数,默认值:always
    ComparisonFunction比较操作通过Comp命令定义,公式左右两边的结果将通过它进行判断,其取值及其意义如下面列表所示:
     

    Pass
    是定义当模板测试(和深度测试)通过时,则根据(stencilOperation值)对模板缓冲值(stencilBufferValue)进行处理,默认值:keep
    stencilOperation命令值列表:

    ReadMask :
    从字面意思的理解就是读遮罩,readMask将和referenceValue以及stencilBufferValue进行按位与(&)操作,readMask取值范围也是0-255的整数,默认值为255,二进制位11111111,即读取的时候不对referenceValue和stencilBufferValue产生效果,读取的还是原始值。
    WriteMask
    是当写入模板缓冲时进行掩码操作(按位与&),writeMask取值范围是0-255的整数,默认值也是255,即当修改stencilBufferValue值时,写入的仍然是原始值。

    和深度测试一样,在unity中,每个像素的模板测试也有它自己一套独立的依据,具体公式如下:

    if(referenceValue&readMask comparisonFunction stencilBufferValue&readMask)

    通过像素

    else

    抛弃像素

    通过的像素操作则根据 stencilOperation命令值 来确定,并更新模板缓冲内的值:

    在更新模板缓冲值的时候,也有writeMask进行掩码操作,用来对特定的位进行写入和屏蔽,默认值为255(11111111),即所有位数全部写入,不进行屏蔽操作。

    参考:Stencil Buffer&Stencil Test

    通过以上的内容,下面来解释 浅谈Unity uGUI Mask组件实现原理 这篇博客中的UI所表现出的挖孔和遮罩效果的原因(一开始就是没明白,所以找了上面一些文档来看)


    场景中的UI均在同一层级,不同的UI后缀,即所用的自定义UI材质:

    蓝色Image 首先绘制,根据UIHole的材质参数: Comp值为6,对应的比较方法为: NotEqual
    在UI被绘制前,对应像素点默认的Stencil值为0,因此蓝色UI通过模板绘制,被绘制;
    Stencil Operation值为0,对应操作为 Keep ,也就是蓝色UI对应像素点的Stencil值保持之前的值,为0

    然后绘制stencil-stencil的UI,Comp值为8,对应的比较方法为:Always
    也就是该UI无论如何都会通过测试,被绘制,那为啥看不见呢?注意这里有个ColorMask的值为0,它会屏蔽UI的颜色输出,实际上stencil-stencil是被绘制了,只是颜色没有输出
    Stencil Operation值为2,对应操作为Replace,也就是材质参数中的Stencil ID 的值被写入 StencilBuffer中 ,所以在绘制完stencil-stencil后,对应UI位置的像素点的值为2

    绘制white-hole的UI,Comp的值为6,对应的比较方法:NotEqual
    由于UIHole材质的Stencil ID值为2,而只有与StencilBuffer的值不相等的对应像素点才会被绘制,所以呈现出white-hole被stencil-stencil挖洞的效果,后面红色的red-hole也是同理

    绘制green-mask的UI,Comp的值为3,对应的比较方法为:Equal
    由于UIHole材质的Stencil ID值为2,而只有与StencilBuffer的值相等的对应像素点才会被绘制,所以呈现出只有在stencil-stencil区域内才显示的遮罩效果,后面的yellow-mask也是同理

    展开全文
  • 这里主要是为了实现短枪动作,脚动手不动的简单实现 1、添加shoot layer射击动作图层2、右键 创建一个avatar mask3、设计遮罩(手动,腿不动)4、配置参数
  • unity3d camera.culling mask 2016-10-26 22:42:58
    总起:Camera.culling Mask,摄像头的剔除掩码,即有选择性的踢掉对应摄像机能渲染的部分场景。操作上,主要通过勾选不同的层,来选择渲染  culling Mask本质为一个Int类型的值,32位,每一位代表一层,比如开启第...
  • SpriteMask 是Unity 2017.1 开始添加2d功能!, SpriteMask 影响的是 Sprite Renderder 组件 官方文档: https://docs.unity3d.com/2017.1/Documentation/Manual/
  • 原理: 使用异或运算【^】 创建一个方法,把要开关的区域传入,采用异或运算方式,就可以开关传入的区域 //设置区域 void SetArea(int areaMask) { //新区域 = 旧区域 ^ 某个区域 nav.areaMask = nav....
  • 2.1.3 cullingMask属性:摄像机按层渲染 基本语法:public intcullingMask { get; set; } 功能说明:此属性用于按层(即GameObject.layer)有选择性的渲染场景中的物体。通过cullingMask可以使得当前摄像机有选择...
  • 博主本来计划在Unity3D游戏开发之从《魂斗罗》游戏说起(上)——目标追踪这篇文章后再写一篇《Unity3D游戏开发之从《魂斗罗》游戏说起(下)》,不过目前博主的项目进度有些缓慢,所以想等项目稳定下来以后再和大家分享...
  • 一、前言 这篇文章是分析UGUI的各种原理,包括层级渲染,事件触发,布局等,教程也比较详细,转过来有空研究一下 ...Unity UGUI 原理篇(一):Canvas 渲染模式 目标 了解各种不同UI ...
  • Unity3D常见面试题 2017-08-11 20:20:00
    Unity3D常见面试题
  • 虽然RenderTexture这个技术是个普遍使用的技术,但是用好它还是要理解他的底层原理和避免一些使用的问题。这里就UNITY3d中的RenderTexure介绍Rendertexture的底层原理和使用时可能遇到的坑和效率问题。
  • 首先介绍一下,阴影的生成,阴影一般是在屏幕空间生成的,利用Unity3D引擎实现阴影的绘制,首先要明白其实现原理,Unity5的Demo已经为我们提供了代码实现,先介绍一下阴影的视线原理: 屏幕空间的阴影实现主要有这么...
  • Unity3d Shader UV移动 2016-07-02 20:43:30
    最终效果(带水平向移动)Unity3d纹理坐标 偏移:Offset(xo,yo),将原点偏移到(xo,yo)。 平铺:Tiling(xt,yt),以偏移后的坐标为新原点,平铺(xt,yt)范围 Unity3d在创建Material,默认Offset = (0, 0),Tiling(1, 1...
  • Unity3D 光照系统(一) 2018-07-12 11:42:48
    光照系统unity3D光照系统Lighting菜单中,一共有6个选项,分别为Directional Light(平行光),Point Light(点光源),Spotlight(聚光灯),Area Light(区域光),Reflection Probe(反射探头),Light Probe ...
  • 最近在项目中有需要用到Mask的理念来实现的一个效果,但是在使用了Unity原生的Mask组件之后发现了一个严重的问题。 就是边缘部分的锯齿化很严重。 经过多方查阅资料,得知原因是 mask的工作原理是根据alpha通道...
  • Unity3D灯光详解 2014-09-01 16:57:09
    Lights will bring personality and flavor to your game. You use lights to illuminate the scenes and objects to create the perfect visual mood. Lights can be used to simulate the sun, burning match ligh
  • Unity3D常用知识点总结 2020-06-18 10:29:01
    Unity3D 可以通过将游戏中的物体拖入新键文件夹来重复使用(往往包括该物体用到的模型,动画,贴图,脚本等等) 右上可以调整Debug还是Normal模式 物体 unity3d下 常用物体 cube cylinder sphere plane quad ...
  • 1.首先找一张圆形图片和长方形图片2.添加Image控件,同时将...原理其实很简单,长方形的图片相当于子物体,圆形图片相当于父物体,子物体覆盖父物体,在父物体上添加Mask组件后,子物体超出父物体的部分,会被自动...
  • Unity中是用int32来表示32个Layer层。int32表示二进制一共有32位(0—31)。 在Unity中可编辑的Layer如下图所示: 在Unity中每个GameObject都有Layer属性,默认的Layer都是Default。在Unity中可编辑的Layer...
  • Unity Mask遮挡模型忽略UI 2017-01-16 17:50:10
    在做ui栏滚动的时候,物品上下滚动,当某个物品在顶格或者在底格的时候,这时候需要滚出去,会有一部分在ui上,一部分要消失,如图:箭头指向的部分需要隐藏掉。开始吧,需要两个相机,一个ui相机,一个ui模型相机,...
  • Unity3D面试题整合 2015-08-16 01:16:45
    Unity3D面试题整合 最近unity3d找工作有些受挫,自己也开始补课了。 下面把这段时间看到的些 面试题供出来让大家也学习下,题目只是面试官选拔人才的一部分,在研究面试题目的过程中,多检测下自己的不足,及时温习...
1 2 3 4 5 ... 20
收藏数 783
精华内容 313