Version: 2022.1
言語: 日本語
ShaderLab コマンド: Offset
ShaderLab コマンド: UsePass

ShaderLab コマンド: Stencil

GPU のステンシルバッファに関する設定を行います。

ステンシルバッファには、フレームバッファ内の各ピクセルの 8 ビットの整数値が格納されています。指定したピクセルに対してフラグメントシェーダーを実行する前に、GPU はステンシルバッファの現在の値を特定のリファレンス値と比較することができます。これをステンシルテストと呼びます。ステンシルテストに合格すると、GPU は深度テストを実行します。ステンシルテストが失敗した場合、GPU はそのピクセルの残りの処理をスキップします。つまり、ステンシルバッファをマスクとして使い、どのピクセルを描画し、どのピクセルを破棄するかを GPU に伝えることができます。

ステンシルバッファは、ポータルやミラーなどの特殊効果に使用するのが一般的です。さらに、ステンシルバッファは、ハードシャドウや 空間領域構成法 (Constructive Solid Geometry, CSG) をレンダリングする際に使用されることもあります。

レンダーパイプラインの互換性

機能名 ビルトインレンダーパイプライン ユニバーサルレンダーパイプライン (URP) HD レンダーパイプライン (HDRP) カスタム SRP
Stencil はい はい はい はい

使用法

このコマンドは、レンダー状態の変更を行います。Pass ブロックで使用すると、そのパスのレンダー状態を設定することができます。また、SubShader ブロックで使用すると、そのサブシェーダー内のすべてのパスのレンダー状態を設定することができます。

Stencil コマンドを使って、ステンシルテストの設定と、GPU がステンシルバッファに書き込む内容の設定という、2 つの異なるタスクを行うことができます。これら 2 つのことを同じコマンドで行うことができますが、最も一般的な使用例は、 1 つのシェーダーオブジェクトを作成し、他のシェーダーオブジェクトが描画できない画面領域をマスクすることです。そのためには、最初のシェーダーオブジェクトが常にステンシルテストに合格し、ステンシルバッファに書き込むように設定し、他のシェーダーオブジェクトがステンシルテストを実行し、ステンシルバッファに書き込まないように設定する必要があります。

RefReadMaskComp パラメーターを使用して、ステンシルテストを設定します。RefWriteMaskPassFailZFail パラメーターを使用して、ステンシルの書き込み操作を設定します。

ステンシルテストの式は以下の通りです。

(ref & readMask) comparisonFunction (stencilBufferValue & readMask)
シグネチャ 構文例 機能
Stencil
{
    Ref <ref>
    ReadMask <readMask>
    WriteMask <writeMask>
    Comp <comparisonOperation>
    Pass <passOperation>
    Fail <failOperation>
    ZFail <zFailOperation>
    CompBack <comparisonOperationBack>
    PassBack <passOperationBack>
    FailBack <failOperationBack>
    ZFailBack <zFailOperationBack>
    CompFront <comparisonOperationFront>
    PassFront <passOperationFront>
    FailFront <failOperationFront>
    ZFailFront <zFailOperationFront>
}

Note that all parameters are optional.
Stencil
{
    Ref 2
    Comp equal
    Pass keep
    ZFail decrWrap
}
指定されたパラメーターに従って、ステンシルバッファを設定します。

有効なパラメーター値

パラメーター Value 機能
ref 整数。範囲は0 - 255。デフォルトは 0。 リファレンス値。

GPU は、comparisonOperation で定義されている演算を使用して、ステンシルバッファの現在のコンテンツをこの値と比較します。

この値は、読み取り操作と書き込み操作のどちらが発生しているかに応じて、readMask または writeMask でマスクされます。

GPU は、Pass、Fail、ZFail の値が Replace の場合、この値をステンシルバッファに書き込むこともできます。
readMask 整数。範囲は0 - 255。デフォルトは 255。 GPU がステンシルテストを行う際に、この値をマスクとして使用します。

ステンシルテストの式については前述を参照してください。
writeMask 整数。範囲は0 - 255。デフォルトは 255。 GPU はステンシルバッファに書き込む際に、この値をマスクとして使用します。

他のマスク同様に、どのビットが操作に含まれるかを指定します。例えば、値が 0 の場合、ステンシルバッファが値 0 を受け取るのではなく、書き込み操作にビットが含まれていないことを意味します。
comparisonOperation 比較演算。有効な値については、比較操作の値 を参照してください。デフォルトは Always。 ステンシルテストのために GPU が全ピクセルに対して行う演算。

面の向きに関わらず、全ピクセルに対する演算を定義します。この演算が comparisonOperationBack と comparisonOperationFront に加えて定義される場合、この値はそれらをオーバーライドします。
passOperation ステンシル演算です。有効な値については、ステンシル演算の値 を参照してください。デフォルトは Keep。 ピクセルがステンシルテストと深度テスト両方をパスしたときに、GPU がステンシルバッファで行う演算。

面の向きに関わらず、全ピクセルに対する演算を定義します。この演算が、comparisonOperationBack と comparisonOperationFront に加えて定義される場合、この値はそれらをオーバーライドします。
failOperation ステンシル演算です。有効な値については、ステンシル演算の値 を参照してください。デフォルトは Keep。 ピクセルがステンシルテストに失敗したときに、GPU がステンシルバッファで行う演算。

面の向きに関わらず、全ピクセルに対する演算を定義します。この演算が、failOperationBack と failOperationFront に加えて定義される場合、この値はそれらをオーバーライドします。
zFailOperation ステンシル演算です。有効な値については、ステンシル演算の値 を参照してください。デフォルトは Keep。 ピクセルがステンシルテストに成功したが、深度テストに失敗したときに、GPU がステンシルバッファで行う演算。

面の向きに関わらず、全ピクセルに対する演算を定義します。この演算が、zFailOperation と zFailOperation に加えて定義される場合、この値はそれらをオーバーライドします。
comparisonOperationBack 比較演算。有効な値については、比較操作の値 を参照してください。デフォルトは Always。 ステンシルテストのために GPU が実行する操作。

後ろ向きピクセル専用の演算を定義します。comparisonOperation が定義されている場合は、その値がこの値よりも優先されます。
passOperationBack ステンシル演算です。有効な値については、ステンシル演算の値 を参照してください。デフォルトは Keep。 ピクセルがステンシルテストと深度テスト両方をパスしたときに、GPU がステンシルバッファで行う演算。

後ろ向きピクセル専用の演算を定義します。passOperation が定義されている場合、この演算はオーバーライドされます。
failOperationBack ステンシル演算です。有効な値については、ステンシル演算の値 を参照してください。デフォルトは Keep。 ピクセルがステンシルテストと深度テスト両方に失敗したときに、GPU がステンシルバッファで行う演算。

後ろ向きピクセル専用の演算を定義します。failOperation が定義されている場合、この演算はオーバーライドされます。
zFailOperationBack ステンシル演算です。有効な値については、ステンシル演算の値 を参照してください。デフォルトは Keep。 ピクセルがステンシルテストにパスしたが、深度テストに失敗したときに、GPU がステンシルバッファで行う演算。

後ろ向きピクセル専用の演算を定義します。zFailOperation が定義されている場合、この演算はオーバーライドされます。
comparisonOperationFront 比較演算。有効な値については、比較操作の値 を参照してください。デフォルトは Always。 ステンシルテストのために GPU が実行する操作。

正面向きピクセル専用の演算を定義します。comparisonOperation が定義されている場合は、この演算はオーバーライドされます。
passOperationFront ステンシル演算です。有効な値については、ステンシル演算の値 を参照してください。デフォルトは Keep。 ピクセルがステンシルテストと深度テスト両方をパスしたときに、GPU がステンシルバッファで行う演算。

正面向きピクセル専用の演算を定義します。passOperation が定義されている場合、この演算はオーバーライドされます。
failOperationFront ステンシル演算です。有効な値については、ステンシル演算の値 を参照してください。デフォルトは Keep。 ピクセルがステンシルテストに失敗したときに、GPUがステンシルバッファに対して行う操作です。

これは、正面向きピクセルのみに対する操作を定義します。failOperation が定義されている場合は、この演算はオーバーライドされます。
zFailOperationFront ステンシル演算です。有効な値については、ステンシル演算の値 を参照してください。デフォルトは Keep。 ピクセルがステンシルテストにパスしたが、深度テストに失敗したときに、GPU がステンシルバッファで行う演算。

正面向きピクセル専用の演算を定義します。zFailOperation が定義されている場合、この演算はオーバーライドされます。

比較演算値

C# では、これらの値は Rendering.CompareFunction enum で示されます。

Value Rendering.CompareFunction enum に対応する整数値 機能
Never 1 ピクセルをまったくレンダリングしません。
Less 2 リファレンス値がステンシルバッファの現在値よりも小さい場合に、ピクセルをレンダリングします。
Equal 3 リファレンス値がステンシルバッファの現在の値と等しい場合に、ピクセルをレンダリングします。
LEqual 4 リファレンス値がステンシルバッファの現在の値以下の場合に、ピクセルをレンダリングします。
Greater 5 リファレンス値がステンシルバッファの現在値よりも大きい場合に、ピクセルをレンダリングします。
NotEqual 6 リファレンス値がステンシルバッファの現在値と異なる場合に、ピクセルをレンダリングします。
GEqual 7 リファレンス値がステンシルバッファの現在の値以上の場合に、ピクセルをレンダリングします。
Always 8 常にピクセルをレンダリングします。

ステンシル演算値

C# では、これらの値は、Rendering.Rendering.StencilOp enum で示されます。

Value Rendering.StencilOp enum に対応する整数値 機能
Keep 0 ステンシルバッファの現在のコンテンツを維持します。
Zero 1 ステンシルバッファに 0 を書き込見ます。
Replace 2 リファレンス値をバッファに書き込みます。
IncrSat 3 バッファの現在値をインクリメントします。値がすでに 255 の場合は 255 のままです。
DecrSat 4 バッファの現在値をデクリメントさせます。値がすでに 0 の場合は 0 のままです。
Invert 5 バッファの現在の値のすべてのビットをネガティブにします。
IncrWrap 6 バッファの現在値をインクリメントします。値がすでに 255 の場合は 0 になります。
DecrWrap 7 バッファの現在値をデクリメントさせます。値がすでに 0 の場合は 255 になります。

Shader "Examples/CommandExample"
{
    SubShader
    {
         // SubShader を定義するコードの残りをここに記述

        Pass
        {    
             // このパスのすべてのピクセルはステンシルテストに合格し、値 2 をステンシルバッファに書き込みます。 
             // 通常、後続のシェーダーがレンダーターゲットのこの領域に描画されないようにするか、この領域のみにレンダリングするよう制限する場合にこれを行います。
             Stencil
             {
                 Ref 2
                 Comp Always
                 Pass Replace
             }            

             // Pass を定義するコードの残りをここに記述
        }
    }
}

このサンプルコードでは、SubShader ブロックでこのコマンドを使用するための構文を示しています。

Shader "Examples/CommandExample"
{
    SubShader
    {
             // このサブシェーダーのすべてのピクセルは、ステンシルバッファの現在の値が 2 未満の場合にのみ、ステンシルテストに合格します。
//通常、"マスクアウト" されていないレンダーターゲットの領域にのみ描画する場合にこれを行います。
            Stencil
             {
                 Ref 2
                 Comp Less
             }  

         // SubShader を定義するコードの残りをここに記述  

        Pass
        {    
              // Pass を定義するコードの残りをここに記述
        }
    }
}
ShaderLab コマンド: Offset
ShaderLab コマンド: UsePass