Unity のシェーダーはテンプレートのテスト Stencil を実装します


序文

Unity のシェーダーはテンプレート テストを実装します


コンポーネントの Mask Mask と Rect Mask 2D は
ここに画像の説明を挿入します
UI のマスクであり、
Sprite Mask はスプライトのマスクです。

1. UIのマスク

1. マスク ——> テンプレート テスト

2、RectMask2D ——> UNITY_UI_CLIP_RECT


2. ステンシルバッファ Stencil は通常、Pass と並行する部分であり、Pass 部分はカラーバッファを書き込みます。

ステンシル:

ステンシル バッファ (StencilBuffer) は、画面上の各ピクセルの符号なし整数値を保存できます。この値の具体的な意味は、プログラムの特定のアプリケーションによって異なります。レンダリング プロセス中に、この値はプリセットと使用できます。 StencilBuffer の値と ReadMask の AND 演算を行った後、Ref 値と比較し、その比較結果に基づいて対応するピクセルのカラー値を更新するかどうかを決定します
。 true の場合は Pass 操作が実行され、それ以外の場合は Fail 操作が実行され、操作値は StencilBuffer に書き込まれる前に WriteMask と AND 演算されます。

ステンシル バッファーのデフォルト値は 0 です。
式: (Ref & ReadMask) Comp (StencilBufferValue & ReadMask)
一般に、読み取りマスク ReadMask がデフォルトであり、変更は行われません。
Stencil
{ Ref [_Stencil] ReadMask [_StencilReadMask] WriteMask [_StencilWriteMask] ] Comp [_StencilComp] ((UnityEngine.Rendering.CompareFunction)) Pass [_StencilOp] (UnityEngine.Rendering.StencilOp)失敗 [_Fail] ZFail [_ZFail] }







Ref: 設定された参照値。この値は、テンプレート バッファ内の値と比較するために使用されます。値の範囲は 0 ~ 255 の整数です。 ReadMask: ReadMask の値は、Ref の値および値と比較されます
。テンプレート バッファー内のビットごとの AND (&) 演算の場合、値の範囲も 0 ~ 255 の整数で、デフォルト値は 255 (バイナリ ビット 11111111) です。つまり、Ref の値とテンプレート バッファー内の値は次のとおりです。読み取り時に変更されず、読み取られた値は元の値のままです。WriteMask
: WriteMask の値は、テンプレート バッファーへの書き込み時に実行されるビット単位の AND 演算です。値の範囲は 0 ~ 255 の整数です。デフォルト値も 255 です。 Comp: Ref とテンプレート バッファを定義します。
の値比較の演算関数、デフォルト値は常にです。
Pass: ステンシル テスト (および深度テスト) に合格すると、ステンシル バッファ値は以下に従って処理されます。失敗: ステンシル
テスト (および深度テスト) に合格し、深度テスト) が失敗した場合、ステンシル バッファー値は (stencilOperation 値) に従って処理され、デフォルト値は keep .
ZFail: ステンシル テストは合格したが深さテストが失敗した場合、ステンシル バッファー値は (stencilOperation 値) に従って処理されます。デフォルト値は keep です。

Comp(比較演算)

Less: 「<」操作と同等、つまり、左側 < 右側の場合のみ、テンプレート テストに合格し、ピクセルがレンダリングされます。 Greater: ">" 操作と同等、つまり
、左側 > 右側、テンプレート テスト
に合格し、ピクセルがレンダリングされます。 Less: 「<=」操作と同等、つまり、左側 <= 右側の場合にのみ、テンプレート テストに合格し、ピクセルがレンダリングされます。 Gequal
: ">= 操作と同等、つまり、左側 >= 右側の場合にのみ、テンプレート テストに合格し、ピクセルがレンダリングされます。 Equal: "= 操作と同等、
つまり、左側 = 右側の場合のみ、テンプレート テストに合格し、ピクセルがレンダリングされます。
NotEqual: 「!=」操作と同等、つまり、左側 = 右側の場合のみ! = 右側では、ステンシル テストに合格し、ピクセルがレンダリングされます。
Always: 式の両側の値に関係なく、常にステンシル テストに合格し、ピクセルがレンダリングされます。
Never: 式の両側の値に関係なく、ステンシル テストに合格し、ピクセルがレンダリングされます。式の両側で、ステンシル テストは常に失敗し、ピクセルは破棄されます。

パス(テンプレートバッファの更新)

Keep: 現在のバッファの内容を保持する、つまり stencilBufferValue を変更しない
Zero: バッファに 0 を書き込む、つまり stencilBufferValue の値が 0 になる
Replace: 参照値をバッファに書き込む、つまり、referenceValue を代入stencilBufferValue.IncrSat
: 現在のステンシル バッファーを変更します。値が 1 増加します。stencilBufferValue が 255 を超える場合は、255 のまま保持されます。つまり、255 以下です。 DecrSat: 現在のステンシル バッファー値を 1 つ減少します
。 stencilBufferValue が 0 を超えると、0 として保持されます。つまり、0 未満ではありません。
NotEqual: 「!=」演算と同等です。つまり、左! の場合のみです。= 右はテンプレートテストがパスし、ピクセルがレンダリングされる
Invert: 現在のステンシルバッファ値(stencilBufferValue)をビットごとに反転
IncrWrap: 現在のバッファ値に1を加算 バッファ値が255を超える場合は0になる, (その後、自動的に増加し続けます)
DecrWrap: 現在のバッファ値を 1 だけ減少させます。バッファ値がすでに 0 の場合は、255 になります (その後、減少し続けます)。


3. 実際の使用方法

1. ステンシルバッファを使用する前に、以下に示すようにマスクレイヤーを設定する必要があります

ここに画像の説明を挿入します

2. 設定後、内部のImageで使用するマテリアルのShaderに以下のコードを追加し、レンダリング後のマスク部分とレンダリング部分のみを実現します。

ここに画像の説明を挿入します

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







ここでのステ​​ンシル ID:1 は、シェーダーの Ref 1 に対応します。
Comp はテンプレート バッファの値を Ref の値と比較する Equal を使用し、
Pass は渡された値を比較して値をバッファに保存する Keep を使用します。

テストコード:

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
        }
    }
}

効果:
画像の説明を追加してください

4.実装されたテンプレートテストをカスタマイズしやすくする

1. プロパティ パネルで int 型を公開し、それを Ref に提供します。

_Ref(“ステンシル参照”,int) = 0

2. Comp が使用できるようにプロパティ パネルで int 型を公開し、それを Unity のいくつかの組み込み列挙型 [Enum(UnityEngine.Rendering.CompareFunction)] に設定します。

[Enum(UnityEngine.Rendering.CompareFunction)]_StencilComp(“ステンシルコンプ”,int) = 0

3. Pass が使用できるようにプロパティ パネルで int 型を公開し、それを Unity のいくつかの組み込み列挙型 [Enum(UnityEngine.Rendering.StencilOp)] に設定します。

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

4. 最終テストコード

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
        }
    }
}

効果:
画像の説明を追加してください

おすすめ

転載: blog.csdn.net/qq_51603875/article/details/133046081