夜風のMixedReality

xRと出会って変わった人生と出会った技術を書き残すためのGeekなHoloRangerの居場所

Unityでステンシル値を任意に変更可能なシェーダーを実装する

本日はMRGT枠です。

MRGTではEnableStencileTestingという項目で一つのシェーダーでマテリアルごとにステンシルプロパティを変えることができます。

この機能を自作シェーダーに組み込んでみます。

〇MRGTの実装

GraphicsToolsStandardShaderの実装は次のようになっています。

 SubShader
    {
        PackageRequirements
        {
            "com.unity.render-pipelines.universal": "10.6.0"
        }

        Tags
        { 
          ・・・    
        }

        // Default pass (only pass outside of the editor).
        Pass
        {
            Name "Main"
   ・・・

            Stencil
            {
                Ref[_StencilReference]
                Comp[_StencilComparison]
                Pass[_StencilOperation]
                ReadMask[_StencilReadMask]
                WriteMask[_StencilWriteMask]
            }

ステンシルとしてのパラメータをPropertiesブロックで定義しています。

Propertiesブロックの実装は次のようにされています。

  Properties
    {
   ・・・
        [Toggle(_STENCIL)] _EnableStencil("Enable Stencil Testing", Float) = 0.0
        _StencilReference("Stencil Reference", Range(0, 255)) = 0
        [Enum(UnityEngine.Rendering.CompareFunction)]_StencilComparison("Stencil Comparison", Int) = 0
        [Enum(UnityEngine.Rendering.StencilOp)]_StencilOperation("Stencil Operation", Int) = 0
        _StencilWriteMask("Stencil Write Mask", Range(0, 255)) = 255
        _StencilReadMask("Stencil Read Mask", Range(0, 255)) = 255
    }
〇UnityEngine.Rendering

UnityEngine.Renderingではその名の通り描画にかかわる様々な機能を提供しています。

UnityEngine.Rendering.CompareFunctionはEnum型で次のようにステンシル操作の定義があります。

| Disabled | 無効 | | Never | ステンシルテストに合格しない | | Less | 新しいステンシル値が古い値より小さい場合合格する | | Equal | ステンシル値が等しい場合に合格する | | LessEqual | ステンシル値が以下の場合合格する | | Greater | ステンシル値が古い値より大きい場合合格する | | NotEqual | ステンシル値が等しくない場合合格する | | GreaterEqual | ステンシル値が自分と同じかそれ以上の場合に合格する | | Always | 常にステンシルテストに合格する |

docs.unity3d.com

UnityEngine.Rendering.StencilOpはステンシルバッファでの処理をEnum型で定義されています。

| Keep | ステンシルバッファを維持する | | Zero | ステンシルバッファをゼロにする | | Replace | ステンシルバッファを置換します | | IncrementSaturate | 現在のステンシルバッファ値を増分。表現可能な最大の符号なし数値に制限します | | DecrementSaturate | 現在のステンシルバッファ値を減分します。最小は 0 に制限します。 | | Invert | ステンシルバッファを反転させます。 | | IncrementWrap | 現在のステンシルバッファ値を増分します。ステンシルバッファ値が最大で表現可能な符号なし数値の場合に増分するときはステンシルバッファ値を 0 にします。 | | DecrementWrap | 現在のステンシルバッファ値を減分します。ステンシルバッファ値が 0 の場合に減分するときはステンシルバッファ値を最大で表現可能な符号なし数値にします。 |

docs.unity3d.com

〇自身のシェーダーに組み込む

今回は次のシェーダーに組み込んでいきます。

Shader "Unlit/NewUnlitShader"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Transparent" }
        LOD 100
        ZTest Always 
        Zwrite On 
        Pass
        {
         }
    }
}

ステンシルを定義します。

Shader "Unlit/NewUnlitShader"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Transparent" }
        LOD 100
        ZTest Always 
        Zwrite On 
        Stencil
            {
                Ref[_StencilReference]
                Comp[_StencilComparison]
                Pass[_StencilOperation]
            }
        Pass
        {
         }
    }
}

最後にPropertiesブロックにステンシルのパラメータを記述します。

          _StencilReference("Stencil Reference", Range(0, 255)) = 0
        [Enum(UnityEngine.Rendering.CompareFunction)]_StencilComparison("Stencil Comparison", Int) = 0
        [Enum(UnityEngine.Rendering.StencilOp)]_StencilOperation("Stencil Operation", Int) = 0

以上でマテリアルごとにステンシル値を任意に設定可能なシェーダーの実装が完了しました。

本日は以上です。