Unity Shader unity文档学习笔记(十六):模板测试StencilTest UGUI Mask遮罩实现

UGUI的Mask也是通过Stencil实现的
在这里插入图片描述
Stencil的所有参数如下

Stencil
{
    Ref 1//Reference Value
    ReadMask 255
    WriteMask 255
    Comp Always //Comparison Function
    Pass Replace
    Fail Keep
    ZFail Replace
}

Ref 就是参考值,当参数允许赋值时,会把参考值赋给当前像素

ReadMask 对当前参考值和已有值进行mask操作,默认值255,一般不用

WriteMask 写入Mask操作,默认值255,一般不用

Comp 比较方法。是拿Ref参考值和当前像素缓存上的值进行比较。默认值always

Greater - 大于
GEqual - 大于等于
Less - 小于
LEqual - 小于等于
Equal - 等于
NotEqual - 不等于
Always - 永远通过
Never - 永远通不过

Pass 当模版测试和深度测试都通过时,进行处理

Fail 当模版测试和深度测试都失败时,进行处理

ZFail 当模版测试通过而深度测试失败时,进行处理

pass,Fail,ZFail都属于Stencil操作,他们参数统一如下:

Keep 保持(即不把参考值赋上去,直接不管)
Zero 归零
Replace 替换(拿参考值替代原有值)
IncrSat 值增加1,但不溢出,如果到255,就不再加
DecrSat 值减少1,但不溢出,值到0就不再减
Invert 反转所有位,如果1就会变成254
IncrWrap 值增加1,会溢出,所以255变成0
DecrWrap 值减少1,会溢出,所以0变成255

一个材质可以给它设置模板的Ref值
然后可以通过模板比较Comp 过滤掉改像素
可以实现遮罩 以及一些其它的效果
在这里插入图片描述
mask遮罩shader

Shader "Unlit/Mask"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" "Queue"="Geometry"}
        //ColorMask 0
        Stencil
        {
            Ref 1
            Comp Always
            Pass Replace
        }
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                return fixed4(0,1,1,1);
            }
            ENDCG
        }
    }
}

其它的shader加上下面的代码就能实现遮罩的效果

 Tags { "RenderType"="Opaque" "Queue"="Geometry+1"}
        Stencil
        {
            Ref 1
            Comp equal
        }

这也是为什么 UGUI的源码 都需要加上一堆Stencil 主要是为了都支持遮罩 然后如果是不需要遮罩的话可以新建一个UGUI材质 另外什么背面剔除啊都可以开一下 奉上一个优化的shader

// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)

Shader "UI/NoMask"
{
    Properties
    {
        [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
        _Color ("Tint", Color) = (1,1,1,1)

		//不需要模板测试 不需要遮罩
        // _StencilComp ("Stencil Comparison", Float) = 8
        // _Stencil ("Stencil ID", Float) = 0
        // _StencilOp ("Stencil Operation", Float) = 0
        // _StencilWriteMask ("Stencil Write Mask", Float) = 255
        // _StencilReadMask ("Stencil Read Mask", Float) = 255

        // _ColorMask ("Color Mask", Float) = 15

        // [Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0
    }

    SubShader
    {
        Tags
        {
            "Queue"="Transparent"
            "IgnoreProjector"="True"
            "RenderType"="Transparent"
            "PreviewType"="Plane"
            "CanUseSpriteAtlas"="True"
        }
		//不需要模板测试 不需要遮罩
        // Stencil
        // {
        //     Ref [_Stencil]
        //     Comp [_StencilComp]
        //     Pass [_StencilOp]
        //     ReadMask [_StencilReadMask]
        //     WriteMask [_StencilWriteMask]
        // }
		//背面剔除可以打开
        //Cull Off
        Lighting Off
        ZWrite Off
        ZTest [unity_GUIZTestMode]
        Blend SrcAlpha OneMinusSrcAlpha
        //ColorMask [_ColorMask]

        Pass
        {
            Name "Default"
        CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma target 2.0

            #include "UnityCG.cginc"
            #include "UnityUI.cginc"

            #pragma multi_compile __ UNITY_UI_CLIP_RECT
           // #pragma multi_compile __ UNITY_UI_ALPHACLIP

            struct appdata_t
            {
                float4 vertex   : POSITION;
                float4 color    : COLOR;
                float2 texcoord : TEXCOORD0;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct v2f
            {
                float4 vertex   : SV_POSITION;
                fixed4 color    : COLOR;
                float2 texcoord  : TEXCOORD0;
               // float4 worldPosition : TEXCOORD1;
                UNITY_VERTEX_OUTPUT_STEREO
            };

            sampler2D _MainTex;
            fixed4 _Color;
            fixed4 _TextureSampleAdd;
           // float4 _ClipRect;
            float4 _MainTex_ST;

            v2f vert(appdata_t v)
            {
                v2f OUT;
                UNITY_SETUP_INSTANCE_ID(v);
                UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
              //  OUT.worldPosition = v.vertex;
                OUT.vertex = UnityObjectToClipPos(v.vertex);

                OUT.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);

                OUT.color = v.color * _Color;
                return OUT;
            }

            fixed4 frag(v2f IN) : SV_Target
            {
                half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color;

                // #ifdef UNITY_UI_CLIP_RECT
                // color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
                // #endif

                // #ifdef UNITY_UI_ALPHACLIP
                // clip (color.a - 0.001);
                // #endif

                return color;
            }
        ENDCG
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_43204246/article/details/118195137