Unity Shader分享Unity干货Unity技术分享

[Shader]3D遮罩

2018-04-17  本文已影响20人  阿飞咯
Stencil
{
    Ref referenceValue //参考值,这个值将用来与模板缓冲中的值进行比较。
    ReadMask  readMask  //读取掩码,取值范围也是0-255的整数,默认值为255,二进制位11111111,即读取的时候不对referenceValue和stencilBufferValue(模板缓冲值)产生效果,读取的还是原始值
    WriteMask writeMask  //输出掩码,当写入模板缓冲时进行掩码操作(按位与【&】),writeMask取值范围是0-255的整数,默认值也是255,即当修改stencilBufferValue值时,写入的仍然是原始值
    Comp comparisonFunction  //条件,关键字有,Greater(>),GEqual(>=),Less(<),LEqual(<=),Equal(=),NotEqual(!=),Always(总是满足),Never(总是不满足)
    Pass stencilOperation  //条件满足后的处理
    Fail stencilOperation  //条件不满足后的处理
    ZFail stencilOperation  //深度测试失败后的处理
}
stencilOperation可用参数:
Keep
保留当前缓冲中的内容,即stencilBufferValue不变。
Zero
将0写入缓冲,即stencilBufferValue值变为0。
Replace
将参考值写入缓冲,即将referenceValue赋值给stencilBufferValue。
IncrSat
stencilBufferValue加1,如果stencilBufferValue超过255了,那么保留为255,即不大于255。
DecrSat
stencilBufferValue减1,如果stencilBufferValue超过为0,那么保留为0,即不小于0。
Invert
将当前模板缓冲值(stencilBufferValue)按位取反
IncrWrap
当前缓冲的值加1,如果缓冲值超过255了,那么变成0,(然后继续自增)。
DecrWrap
当前缓冲的值减1,如果缓冲值已经为0,那么变成255,(然后继续自减)。

主要是使用Stencil,关于Stencil可参考

mask先渲染,将缓冲区的值设为1

    Stencil{
        Ref 1
        Comp Always
        Pass Replace
    }

需要添加遮罩的后渲染,判断缓冲区的值是否为1

    Stencil{
        Ref 1
        Comp equal
    }

控制渲染顺序可以用Queue,值越小越先渲染,也可以使用Canvas设置层级
(经测试 UGUI的Mask组件也是Ref 1,同时使用可能会有冲突)

完整代码:

Shader "Unlit/3dmask"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Tags {
            "RenderType"="Opaque"
            "Queue" = "Transparent"
            }
        LOD 100
        Stencil{
            Ref 1
            Comp Always
            Pass Replace
        }
        Blend SrcAlpha OneMinusSrcAlpha
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog
            
            #include "UnityCG.cginc"

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

            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                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);
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }
            
            fixed4 frag (v2f i) : SV_Target
            {
                return 0;
            }
            ENDCG
        }
    }
}

Shader "Unlit/Additive Mask"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Tags { 
            "RenderType"="Opaque"
            "Queue" = "Transparent+1"
            }
        LOD 100
        Stencil{
                Ref 1
                Comp equal
            }
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog
            
            #include "UnityCG.cginc"
            
            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                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);
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }
            
            fixed4 frag (v2f i) : SV_Target
            {
                // sample the texture
                fixed4 col = tex2D(_MainTex, i.uv);
                // apply fog
                UNITY_APPLY_FOG(i.fogCoord, col);
                return col;
            }
            ENDCG
        }
    }
}

上一篇下一篇

猜你喜欢

热点阅读