Shader in Unity implements template testing Stencil


Preface

Shader in Unity implements template testing


Mask Mask and Rect Mask 2D in the component
Insert image description here
are the Mask in the UI,
and Sprite Mask is the Mask in the sprite.

1. Mask in UI

1. Mask ——> template test

2、RectMask2D ——> UNITY_UI_CLIP_RECT


2. The stencil buffer Stencil is generally a part parallel to the Pass. The Pass part writes the color buffer.

Stencil:

The stencil buffer (StencilBuffer) can save an unsigned integer value for each pixel on the screen. The specific meaning of this value depends on the specific application of the program. During the rendering process, this value can be used with a preset Compare it with the reference value, and decide whether to update the color value of the corresponding pixel based on the comparison result. This comparison process is called template testing. The value of StencilBuffer is ANDed with ReadMask, and then compared with the Ref value. The
result When it is true, the Pass operation is performed, otherwise the Fail operation is performed, and the operation value is ANDed with WriteMask before being written to the StencilBuffer.

The default value in the stencil buffer is: 0
formula: (Ref & ReadMask) Comp (StencilBufferValue & ReadMask)
Generally, the read mask ReadMask is the default, no modification is made
Stencil
{ Ref [_Stencil] ReadMask [_StencilReadMask] WriteMask [_StencilWriteMask] Comp [_StencilComp] ((UnityEngine.Rendering.CompareFunction)) Pass [_StencilOp] (UnityEngine.Rendering.StencilOp) Fail [_Fail] ZFail [_ZFail] }







Ref: The set reference value. This value will be used to compare with the value in the template buffer. The value range is an integer from 0 to 255. ReadMask: The value
of ReadMask will be compared with the value of Ref and the value in the template buffer. Bitwise AND (&) operation, the value range is also an integer from 0-255, the default value is 255 (binary bit 11111111), that is, the value of Ref and the value in the template buffer are not modified when reading, and the value read is still Original value.
WriteMask: The value of WriteMask is the bitwise AND operation performed when writing to the template buffer. The value range is an integer from 0 to 255. The default value is also 255, that is, no modification is made. Comp: Define Ref and template
buffer The operation function for value comparison in , the default value is always.
Pass: When the stencil test (and depth test) passes, the stencil buffer value is processed according to (stencilOperation value), the default value is keep. Fail:
When the stencil test (and depth test) is passed and depth test) fails, the stencil buffer value is processed according to (stencilOperation value), and the default value is keep.
ZFail: When the stencil test passes but the depth test fails, the stencil buffer value is processed according to (stencilOperation value). The default value is keep

Comp (comparison operation)

Less: Equivalent to the "<" operation, that is, only when the left side < the right side, the template test passes, and the pixel is rendered. Greater: Equivalent
to the ">" operation, that is, only when the left side > the right side, the template test passes, and the pixel is rendered.
Less: Equivalent to "<=" operation, that is, only if the left side <= the right side, the template test passes, and the pixel is rendered.
Gequal: Equivalent to the ">=" operation, that is, only if the left side >= the right side, the template test passes, and the pixel is rendered.
Equal: Equivalent to "=" operation, that is, only if the left side = right side, the template test passes, and the pixel is rendered.
NotEqual: Equivalent to the "!=" operation, that is, only if the left side! = on the right, the stencil test passes and the pixel is rendered.
Always: Regardless of the values ​​on both sides of the formula, the stencil test always passes and the pixel is rendered.
Never: Regardless of the values ​​on both sides of the formula, the stencil test always fails and the pixel is discarded.

Pass (update of template buffer)

Keep: Keep the contents of the current buffer, that is, stencilBufferValue remains unchanged.
Zero: Write 0 to the buffer, that is, the stencilBufferValue value becomes 0.
Replace: Write the reference value to the buffer, that is, assign referenceValue to stencilBufferValue.
IncrSat: Change the current stencil buffer The value is increased by 1. If stencilBufferValue exceeds 255, then it is retained as 255, that is, it is not greater than 255.
DecrSat: Decrease the current stencil buffer value by 1. If stencilBufferValue exceeds 0, then it is retained as 0, that is, it is not less than 0.
NotEqual: Equivalent to "!=" operation, that is, only if the left! = On the right, the template test passes and the pixel is rendered.
Invert: Invert the current stencil buffer value (stencilBufferValue) bit by bit.
IncrWrap: Add 1 to the current buffer value. If the buffer value exceeds 255, it becomes 0, (and then continues automatically Increase).
DecrWrap: Decrease the current buffer value by 1. If the buffer value is already 0, it becomes 255 (and then continues to decrement).


3. Actual use

1. Before using the stencil buffer, you need to set a mask layer as shown below

Insert image description here

2. After setting up, add the following code to the Shader of the material used by the inner Image to achieve only the masked part and the rendered part after rendering.

Insert image description here

Stencil
{
Ref 1
//ReadMask [_StencilReadMask]
//WriteMask [_StencilWriteMask]
Comp Equal
Pass Keep
//Fail [_Fail]
//ZFail [_ZFail]
}

The Stencil Id:1 here corresponds to Ref 1 in the Shader.
Comp uses Equal, which uses the value of the template buffer to the value of Ref.
Pass uses Keep, which compares the passed value and saves the value in the buffer.

Test code:

Shader"MyShader/P1_1_6"
{
    Properties
    {
        //命名要按标准来,这个属性才可以和Unity组件中的属性产生关联
        //比如说,在更改 Image 的源图片时,同时更改这个
        [PerRendererData]_MainTex("MainTex",2D) = "white"{}
       
    }
    
    SubShader
    {
        //更改渲染队列(UI的渲染队列一般是半透明层的)
        Tags {"Queue" = "TransParent"}
        //混合模式
        Blend SrcAlpha OneMinusSrcAlpha
        
        Stencil
         {
            Ref 1
            //ReadMask [_StencilReadMask]
            //WriteMask [_StencilWriteMask]
            Comp Equal
            Pass Keep
            //Fail [_Fail]
            //ZFail [_ZFail]
        }
        Pass
        {
            CGPROGRAM
            #pragma vertex  vert
            #pragma fragment frag
            #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
            {
                fixed4 mainTex = tex2D(_MainTex,i.uv);
                return  mainTex * i.color;
            }
            
            ENDCG
        }
    }
}

Effect:
Please add image description

4. Make the implemented template test more convenient to customize

1. Expose an int type in the property panel and provide it to Ref.

_Ref(“Stencil Ref”,int) = 0

2. Expose an int type in the property panel for Comp to use, and set it to several of Unity’s built-in enumeration types [Enum(UnityEngine.Rendering.CompareFunction)]

[Enum(UnityEngine.Rendering.CompareFunction)]_StencilComp(“Stencil Comp”,int) = 0

3. Expose an int type in the property panel for Pass to use, and set it to several of Unity’s built-in enumeration types [Enum(UnityEngine.Rendering.StencilOp)]

[Enum(UnityEngine.Rendering.StencilOp)]_StencilOp(“Stencil Op”,int) = 0

4. Final test code

Shader"MyShader/P1_1_6"
{
    Properties
    {
        //命名要按标准来,这个属性才可以和Unity组件中的属性产生关联
        //比如说,在更改 Image 的源图片时,同时更改这个
        [PerRendererData]_MainTex("MainTex",2D) = "white"{}
        //暴露一个变量来供模板测试中 Ref 使用
        _Ref("Stencil Ref",int) = 0
        //暴露一个变量来供模板测试中 Comp 使用
        [Enum(UnityEngine.Rendering.CompareFunction)]_StencilComp("Stencil Comp",int) = 0
        
        [Enum(UnityEngine.Rendering.StencilOp)]_StencilOp("Stencil Op",int) = 0
    }
    
    SubShader
    {
        //更改渲染队列(UI的渲染队列一般是半透明层的)
        Tags {"Queue" = "TransParent"}
        //混合模式
        Blend SrcAlpha OneMinusSrcAlpha
        
        Stencil
        {
            Ref [_Ref]
            //以下两个属性一般不做修改
            //ReadMask [_StencilReadMask]
            //WriteMask [_StencilWriteMask]
            Comp [_StencilComp]
            Pass [_StencilOp]
            //Fail [_Fail]
            //ZFail [_ZFail]
        }
        Pass
        {
            CGPROGRAM
            #pragma vertex  vert
            #pragma fragment frag
            #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
            {
                fixed4 mainTex = tex2D(_MainTex,i.uv);
                return  mainTex * i.color;
            }
            
            ENDCG
        }
    }
}

Effect:
Please add image description

Guess you like

Origin blog.csdn.net/qq_51603875/article/details/133046081