Unity中UI Shader遮罩RectMask2D

这篇具有很好参考价值的文章主要介绍了Unity中UI Shader遮罩RectMask2D。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


前言

Unity中UI Shader遮罩RectMask2D


一、需要定义一个变体UNITY_UI_CLIP_RECT

UNITY_UI_CLIP_RECT

当父级物体有Rect Mask 2D组件时激活.
需要先手动定义此变体#pragma multi_compile _ UNITY_UI_CLIP_RECT
同时需要声明:_ClipRect(一个四维向量,四个分量分别表示RectMask2D的左下角点的xy坐标与右上角点的xy坐标.)
UnityGet2DClipping (float2 position, float4 clipRect)即可实现遮罩.

//声明一个变体,用于RectMask使用
#pragma multi_compile _ UNITY_UI_CLIP_RECT

注意: 上面的 _ 前后均有空格

在片元着色器使用以下代码测试看看基本功能
#if UNITY_UI_CLIP_RECT
return 1;
#else
return 0.5;
#endif

测试代码:

Shader"MyShader/P1_1_8"
{
    Properties
    {
        //命名要按标准来,这个属性才可以和Unity组件中的属性产生关联
        //比如说,在更改 Image 的源图片时,同时更改这个
        [PerRendererData]_MainTex("MainTex",2D) = "white"{}
        _StencilComp ("Stencil Comparison", Float) = 8.000000
        _Stencil ("Stencil ID", Float) = 0.000000
        _StencilOp ("Stencil Operation", Float) = 0.000000
        _StencilWriteMask ("Stencil Write Mask", Float) = 255.000000
        _StencilReadMask ("Stencil Read Mask", Float) = 255.000000
        _ColorMask ("Color Mask", Float) = 15.000000
    }
    
    SubShader
    {
        //更改渲染队列(UI的渲染队列一般是半透明层的)
        Tags {"Queue" = "TransParent"}
        //混合模式
        Blend SrcAlpha OneMinusSrcAlpha
        
        ColorMask [_ColorMask]
        
        Stencil
        {
            Ref [_Stencil]
            ReadMask [_StencilReadMask]
            WriteMask [_StencilWriteMask]
            Comp [_StencilComp]
            Pass [_StencilOp]
        }
        Pass
        {
            CGPROGRAM
            #pragma vertex  vert
            #pragma fragment frag
            //声明一个变体,用于RectMask使用
            #pragma multi_compile _ UNITY_UI_CLIP_RECT
            #include "UnityCG.cginc"
            //存储 应用程序输入到顶点着色器的信息
            struct appdata
            {
                //顶点信息
                float4 vertex:POSITION;
                float2 uv : TEXCOORD;
                //这里定义一个语义为Color的4维向量,用于传入顶点颜色,设置语义为COLOR后,这个变量就会与顶点颜色对应
                fixed4 color:COLOR;
            };
            //存储 顶点着色器输入到片元着色器的信息
            struct v2f
            {
                //裁剪空间下的位置信息(SV_POSITION是必须的)
                float4 pos:SV_POSITION;
                float2 uv : TEXCOORD;
                //这里的语义主要代表精度不同,TEXCOORD 在这里只是代表高精度
                fixed4 color : TEXCOORD1;
            };
            
            sampler2D _MainTex;
            fixed4 _Color;
            v2f vert(appdata v)
            {
                v2f o;
                //把顶点信息转化到裁剪坐标下
                o.pos = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                o.color = v.color;
                return o;
            }
            fixed4 frag(v2f i) : SV_Target
            {
                #if UNITY_UI_CLIP_RECT
                    return  1;
                #else
                    return 0.5;
                #endif
                
                
                fixed4 mainTex = tex2D(_MainTex,i.uv);
                return  mainTex * i.color;
            }
            
            ENDCG
        }
    }
}

效果:
Unity中UI Shader遮罩RectMask2D,Unity,unity,ui,游戏引擎
Unity中UI Shader遮罩RectMask2D,Unity,unity,ui,游戏引擎


二、需要申明一个_ClipRect,这是使用上面这个变体需要使用的,这个属性并没有在Properties声明

同时需要声明:_ClipRect(一个四维向量,四个分量分别表示RectMask2D的左下角点的xy坐标与右上角点的xy坐标.)

这个坐标是用来存储RectMask所占的位置信息
因为UI是一个矩形,所以记录了 左下角 和 右上角 顶点信息 后就可以知道 RectMask所占的位置
Unity中UI Shader遮罩RectMask2D,Unity,unity,ui,游戏引擎

注意:在UGUI中模型顶点的本地坐标,经过顶点着色器传入片段着色器会转化为屏幕坐标(即看见的坐标值很大不是UI模型的本地坐标,而是UI模型的屏幕坐标)

1、现在我们用简单的代码测试一下 _ClipRect 的使用

主要逻辑:
1、在应用程序阶段传入顶点着色器的结构体中 加入 顶点信息
2、在顶点着色着色器传入片元着色器的结构体中 加入 顶点信息
3、在 片元着色器中,使用 _ClipRect 的坐标信息用于判断,符合条件的返回 1(半透明白) ,不符合返回 0.5(半透明灰)

Shader"MyShader/P1_1_8"
{
    Properties
    {
        //命名要按标准来,这个属性才可以和Unity组件中的属性产生关联
        //比如说,在更改 Image 的源图片时,同时更改这个
        [PerRendererData]_MainTex("MainTex",2D) = "white"{}
        _StencilComp ("Stencil Comparison", Float) = 8.000000
        _Stencil ("Stencil ID", Float) = 0.000000
        _StencilOp ("Stencil Operation", Float) = 0.000000
        _StencilWriteMask ("Stencil Write Mask", Float) = 255.000000
        _StencilReadMask ("Stencil Read Mask", Float) = 255.000000
        _ColorMask ("Color Mask", Float) = 15.000000
    }
    
    SubShader
    {
        //更改渲染队列(UI的渲染队列一般是半透明层的)
        Tags {"Queue" = "TransParent"}
        //混合模式
        Blend SrcAlpha OneMinusSrcAlpha
        
        ColorMask [_ColorMask]
        
        Stencil
        {
            Ref [_Stencil]
            ReadMask [_StencilReadMask]
            WriteMask [_StencilWriteMask]
            Comp [_StencilComp]
            Pass [_StencilOp]
        }
        Pass
        {
            CGPROGRAM
            #pragma vertex  vert
            #pragma fragment frag
            //声明一个变体,用于RectMask使用
            #pragma multi_compile _ UNITY_UI_CLIP_RECT
            #include "UnityCG.cginc"
            //存储 应用程序输入到顶点着色器的信息
            struct appdata
            {
                //顶点信息
                float4 vertex:POSITION;
                float2 uv : TEXCOORD;
                //这里定义一个语义为Color的4维向量,用于传入顶点颜色,设置语义为COLOR后,这个变量就会与顶点颜色对应
                fixed4 color:COLOR;
            };
            //存储 顶点着色器输入到片元着色器的信息
            struct v2f
            {
                //裁剪空间下的位置信息(SV_POSITION是必须的)
                float4 pos:SV_POSITION;
                float2 uv : TEXCOORD;
                //这里的语义主要代表精度不同,TEXCOORD 在这里只是代表高精度
                fixed4 color : COLOR;
                //定义一个四维变量存储顶点信息
                float4 vertex : TEXCOORD1;
            };
            
            sampler2D _MainTex;
            fixed4 _Color;
            //在使用 RectMask 需要使用的变体时,需要声明一个四维变量 _ClipRect
            float4 _ClipRect;
            
            
            v2f vert(appdata v)
            {
                v2f o;
                //把顶点信息转化到裁剪坐标下
                o.pos = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                o.color = v.color;
                o.vertex = v.vertex;
                return o;
            }
            fixed4 frag(v2f i) : SV_Target
            {
                #if UNITY_UI_CLIP_RECT
                    if(_ClipRect.x < i.vertex.x)
                    {
                        return 1;
                    }
                    else
                    {
                        return 0.5;
                    }
                #else
                    return 0.5;
                #endif
                
                fixed4 mainTex = tex2D(_MainTex,i.uv);
                return  mainTex * i.color;
            }
            
            ENDCG
        }
    }
}

效果:
Unity中UI Shader遮罩RectMask2D,Unity,unity,ui,游戏引擎

然后我们基于以上的基础,让 内层UI只在 _ClipRect 范围内渲染

测试代码:

Shader"MyShader/P1_1_8"
{
    Properties
    {
        //命名要按标准来,这个属性才可以和Unity组件中的属性产生关联
        //比如说,在更改 Image 的源图片时,同时更改这个
        [PerRendererData]_MainTex("MainTex",2D) = "white"{}
        _StencilComp ("Stencil Comparison", Float) = 8.000000
        _Stencil ("Stencil ID", Float) = 0.000000
        _StencilOp ("Stencil Operation", Float) = 0.000000
        _StencilWriteMask ("Stencil Write Mask", Float) = 255.000000
        _StencilReadMask ("Stencil Read Mask", Float) = 255.000000
        _ColorMask ("Color Mask", Float) = 15.000000
    }
    
    SubShader
    {
        //更改渲染队列(UI的渲染队列一般是半透明层的)
        Tags {"Queue" = "TransParent"}
        //混合模式
        Blend SrcAlpha OneMinusSrcAlpha
        
        ColorMask [_ColorMask]
        
        Stencil
        {
            Ref [_Stencil]
            ReadMask [_StencilReadMask]
            WriteMask [_StencilWriteMask]
            Comp [_StencilComp]
            Pass [_StencilOp]
        }
        Pass
        {
            CGPROGRAM
            #pragma vertex  vert
            #pragma fragment frag
            //声明一个变体,用于RectMask使用
            #pragma multi_compile _ UNITY_UI_CLIP_RECT
            #include "UnityCG.cginc"
            //存储 应用程序输入到顶点着色器的信息
            struct appdata
            {
                //顶点信息
                float4 vertex:POSITION;
                float2 uv : TEXCOORD;
                //这里定义一个语义为Color的4维向量,用于传入顶点颜色,设置语义为COLOR后,这个变量就会与顶点颜色对应
                fixed4 color:COLOR;
            };
            //存储 顶点着色器输入到片元着色器的信息
            struct v2f
            {
                //裁剪空间下的位置信息(SV_POSITION是必须的)
                float4 pos:SV_POSITION;
                float2 uv : TEXCOORD;
                //这里的语义主要代表精度不同,TEXCOORD 在这里只是代表高精度
                fixed4 color : COLOR;
                //定义一个四维变量存储顶点信息
                float4 vertex : TEXCOORD1;
            };
            
            sampler2D _MainTex;
            fixed4 _Color;
            //在使用 RectMask 需要使用的变体时,需要声明一个四维变量 _ClipRect
            float4 _ClipRect;
            
            
            v2f vert(appdata v)
            {
                v2f o;
                //把顶点信息转化到裁剪坐标下
                o.pos = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                o.color = v.color;
                o.vertex = v.vertex;
                return o;
            }
            fixed4 frag(v2f i) : SV_Target
            {
                #if UNITY_UI_CLIP_RECT
                    if(_ClipRect.x < i.vertex.x && _ClipRect.z > i.vertex.x && _ClipRect.y < i.vertex.y && _ClipRect.w > i.vertex.y)
                    {
                        fixed4 mainTex = tex2D(_MainTex,i.uv);
                        return  mainTex * i.color;
                    }
                    else
                    {
                        return 0;
                    }
                #else
                    return 0.5;
                #endif
                
                
            }
            
            ENDCG
        }
    }
}

效果:
Unity中UI Shader遮罩RectMask2D,Unity,unity,ui,游戏引擎

2、因为 if 语句在 Shader 中十分消耗性能,所以要避免使用 if 语句 ,if只适合用于理解原理(三目运算符也是同理)

我们使用Math中的 step(a,b) 函数来解决这个问题
如果a<=b返回1,否则返回0.

如果使用 这个 Math 方法,则可以按这样的思路设计,使用宏判断后,在宏判断中记录 step 后的值,然后最后与需要输出的颜色混合输出即可。(因为0乘任何数等于0)

所以这里把之前的条件语句转化为了如下语句
value = step(_ClipRect.x,i.vertex.x) * step(i.vertex.x,_ClipRect.z) * step(_ClipRect.y,i.vertex.y) * step(i.vertex.y,_ClipRect.w);

3、以上代码还可以再进一步优化,因为 step 不只可以用与点之间的比较,可以用于向量之间的比较,所以在以上代码的基础上,减少step的使用

fixed2 rect = step(_ClipRect.xy,i.vertex.xy) * step(i.vertex.xy,_ClipRect.zw);
value = rect.x * rect.y ;

因为我们使用的混合模式为

Blend SrcAlpha OneMinusSrcAlpha

所以使用 纹理采样后的透明值 与输出结果相乘,即可让透明部分透明

return mainTex * i.color * value * mainTex.a;

4、使用 UnityGet2DClipping (float2 position, float4 clipRect)

需要导入库:#include <UnityUI.cginc>

value = UnityGet2DClipping(i.vertex,_ClipRect);
//函数实现 和 法3一样文章来源地址https://www.toymoban.com/news/detail-731136.html

5、最终测试代码

Shader"MyShader/P1_1_9"
{
    Properties
    {
        //命名要按标准来,这个属性才可以和Unity组件中的属性产生关联
        //比如说,在更改 Image 的源图片时,同时更改这个
        [PerRendererData]_MainTex("MainTex",2D) = "white"{}
        _StencilComp ("Stencil Comparison", Float) = 8.000000
        _Stencil ("Stencil ID", Float) = 0.000000
        _StencilOp ("Stencil Operation", Float) = 0.000000
        _StencilWriteMask ("Stencil Write Mask", Float) = 255.000000
        _StencilReadMask ("Stencil Read Mask", Float) = 255.000000
        _ColorMask ("Color Mask", Float) = 15.000000
    }
    
    SubShader
    {
        //更改渲染队列(UI的渲染队列一般是半透明层的)
        Tags {"Queue" = "TransParent"}
        //混合模式
        Blend SrcAlpha OneMinusSrcAlpha
        
        ColorMask [_ColorMask]
        
        Stencil
        {
            Ref [_Stencil]
            ReadMask [_StencilReadMask]
            WriteMask [_StencilWriteMask]
            Comp [_StencilComp]
            Pass [_StencilOp]
        }
        Pass
        {
            CGPROGRAM
            #pragma vertex  vert
            #pragma fragment frag
            //声明一个变体,用于RectMask使用
            #pragma multi_compile _ UNITY_UI_CLIP_RECT
            #include <UnityUI.cginc>

            #include "UnityCG.cginc"
            //存储 应用程序输入到顶点着色器的信息
            struct appdata
            {
                //顶点信息
                float4 vertex:POSITION;
                float2 uv : TEXCOORD;
                //这里定义一个语义为Color的4维向量,用于传入顶点颜色,设置语义为COLOR后,这个变量就会与顶点颜色对应
                fixed4 color:COLOR;
            };
            //存储 顶点着色器输入到片元着色器的信息
            struct v2f
            {
                //裁剪空间下的位置信息(SV_POSITION是必须的)
                float4 pos:SV_POSITION;
                float2 uv : TEXCOORD;
                //这里的语义主要代表精度不同,TEXCOORD 在这里只是代表高精度
                fixed4 color : COLOR;
                //定义一个四维变量存储顶点信息
                float4 vertex : TEXCOORD1;
            };
            
            sampler2D _MainTex;
            fixed4 _Color;
            //在使用 RectMask 需要使用的变体时,需要声明一个四维变量 _ClipRect
            float4 _ClipRect;
            
            
            v2f vert(appdata v)
            {
                v2f o;
                //把顶点信息转化到裁剪坐标下
                o.pos = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                o.color = v.color;
                o.vertex = v.vertex;
                return o;
            }
            fixed4 frag(v2f i) : SV_Target
            {
                float value = 0;
                #if UNITY_UI_CLIP_RECT
                    //法1、使用if有助于理解
                    /*if(_ClipRect.x < i.vertex.x && _ClipRect.z > i.vertex.x && _ClipRect.y < i.vertex.y && _ClipRect.w > i.vertex.y)
                    {
                        return 1;
                    }
                    else
                    {
                        return 0;
                    }*/
                    //法2、利用step来优化if
                    //value =  step(_ClipRect.x,i.vertex.x) * step(i.vertex.x,_ClipRect.z) * step(_ClipRect.y,i.vertex.y) * step(i.vertex.y,_ClipRect.w);
                    //法3、使用step进行向量比较,减少step的使用数量
                    /*fixed2 rect = step(_ClipRect.xy,i.vertex.xy) * step(i.vertex.xy,_ClipRect.zw);
                    value = rect.x * rect.y;*/
                    //法4、利用Unity自带函数实现
                    value = UnityGet2DClipping(i.vertex,_ClipRect);
                #else
                    return 0.5;
                #endif
                
                fixed4 mainTex = tex2D(_MainTex,i.uv);
                return  mainTex * i.color * value * mainTex.a;
            }
            
            ENDCG
        }
    }
}

到了这里,关于Unity中UI Shader遮罩RectMask2D的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Unity3D Shader 引导遮罩,支持圆形、矩形、圆角矩形框

    unity3D新手引导遮罩,支持圆形,矩形框,圆角矩形框。图形位置和大小可以根据控件的位置和大小调节,通用所有分辨率设备。黄色区域遮挡,只有白色区域可以点穿。 原文链接:https://www.kadastudio.cn/archives/89 ​ 将MyGuideMask挂载到脚本上,然后通过GuideMask创建材质并赋值,根据

    2024年02月11日
    浏览(51)
  • 【Unity实战100例】用户头像圆形遮罩使用Shader不用Mask组件

    目录 一.创建材质 二.创建Shader文件编写Shader代码 三.Image材质设置 源码:https://download.csdn.net/download/qq_37310110/88196529 前言:我们在使用Unity的自带组件Mask的时候会出现毛边现象很难处理掉,这里我们使用着色

    2024年02月19日
    浏览(52)
  • Unity Shader ASE基础效果思路与代码(一):遮罩、硬边溶解、光边溶解、UV扰动

    效果展示: 思路与代码 :主纹理和遮罩纹理相乘,其中,两个纹理给到UV流动 步骤与详解 :panner节点:平移 效果展示: 思路与代码 :原图和噪声贴图的透明通道混合,改变噪声贴图的透明度即可 步骤与详解 : 在SubShader中关掉深度写入,混合模式为Alpha Blend,Tags设为透明

    2024年02月22日
    浏览(55)
  • unity UI特效遮罩

    ParticleSystemRenderer-maskInteraction - Unity 脚本 API

    2024年01月19日
    浏览(50)
  • Unity Shader - UI/Default shader 优化示例

    Unity : 2020.3.37f1 Pipeline : BRP 做性能优化都是慢慢都扣出来的 当然,优先处理 top 热点的 但是一些就算不是 top,但是像素面积有多,overdraw 也多不可小觑 当然,如果你能找到性能热点,那还是优先分析一下哪些 shader 占的 cycles 最高,和 A, L/S, T, 最高 还有 register 的数量尽可能

    2024年02月07日
    浏览(44)
  • Unity中Shader实现UI流光效果

    在很多游戏的 UI 中,都有实现 一道光扫过 UI 的效果 Unity中Shader的时间_Time 注意: 因为,这是UGUI的Shader,记着修改渲染顺序为 透明层级 和 混合模式 Tags {“Queue” = “TransParent”} Blend SrcAlpha OneMinusSrcAlpha 代码: 效果: Unity3D Shader系列之UI流光效果 Unity流光shader,无需图片

    2024年02月05日
    浏览(53)
  • Unity UI.Image 六边形+流光 Shader

    效果图 参考代码  

    2024年02月11日
    浏览(51)
  • 【Unity Shader】Special Effects(八)Wireframe 线框化(UI)

    更新日期:2023年6月17日。 Github源码:[点我获取源码] 线框化 效果可以将一张图像根据纹理轮廓转换为纯线框的图像,效果如下:

    2024年02月10日
    浏览(32)
  • 【Unity100个实用小技巧】如何修改UI上材质的Shader

    ☀️博客主页:CSDN博客主页 💨本文由 萌萌的小木屋 原创,首发于 CSDN 💢 🔥学习专栏推荐:面试汇总 ❗️游戏框架专栏推荐:游戏实用框架专栏 ⛅️点赞 👍 收藏 ⭐留言 📝,如有错误请指正 📆 未来很长,值得我们全力奔赴更美好的生活✨ ------------------❤️分割线❤

    2024年02月14日
    浏览(50)
  • 【unity插件】Shader实现UGUI的特效——UIEffect为 Unity UI 提供视觉效果组件

    一般的shader无法直接使用在UI上,需要在shader中定义特定的面板参数,今天就来推荐github上大佬做的一套开源的一系列UGUI,Shader实现的特效——UIEffect 为 Unity UI 提供视觉效果组件。 https://github.com/Ankh4396/UIEffect 让我们用效果来装饰你的UI!您可以根据需要从脚本和检查器中控

    2024年02月04日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包