ステンシルバッファについてはこちらの記事が詳しいです。
ステンシルバッファ | wgld.org
上記サイトから説明を引用させてもらうと、
ステンシル( stencil )は直訳すると[ 型紙 ]や[ 原紙 ]といった意味になる言葉で、3D プログラミングにおいては[ 型抜き ]という意味としてステンシルバッファは利用されています。
ということ。
要は、3Dのオブジェクトにマスクを掛けることができる、というものです。
そして当然、Unityでも同じように処理することが可能です。(Unityのドキュメントはこちら)
サンプルコード
Unityのドキュメントに書かれているコードを引用すると、以下のように記述します。
Shader "Red" {
SubShader {
Tags { "RenderType"="Opaque" "Queue"="Geometry"}
Pass {
Stencil {
Ref 2
Comp always
Pass replace
ZFail decrWrap
}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
struct appdata {
float4 vertex : POSITION;
};
struct v2f {
float4 pos : SV_POSITION;
};
v2f vert(appdata v) {
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
return o;
}
half4 frag(v2f i) : COLOR {
return half4(1,0,0,1);
}
ENDCG
}
}
}
具体的には
Stencil {
Ref 2
Comp always
Pass replace
ZFail decrWrap
}
の部分がステンシルを実行している箇所です。
解説の詳細は最初に紹介した記事を見ていただいたほうがいいので割愛します。
概要としてはシェーダの役割である「ピクセルに対するレンダリング」を行う際、該当のシェーダのピクセルをレンダリングすべきかどうか、の判断を行うために使われるのがこの ステンシルバッファ です。
つまり、このステンシルバッファを使った「ステンシルテスト」に合格しなかった場合はそのシェーダの該当ピクセルへのレンダリングはたんに無視されます。
そして、現在計算中のピクセルに対してのステンシルテストの結果によって該当ピクセルのステンシル値の値が変更されます。
変更されうるステータスとしては以下の3つがあります。
- 合格
- 不合格
- 合格したが深度テスト不合格
合格/不合格は読んで字のごとくなので問題ないでしょう。
最後の項目は、「ステンシルテストには合格したが、深度テストが不合格でピクセルがレンダリングされなかった場合」にどうするかを決めるものとなります。
(ピクセルがレンダリングされるかどうかは、ステンシル以外にも深度値によるテストがあるためです)
ステンシルの設定については以下の構文になっています。
構文
Ref [整数値]
Comp [比較関数]
Pass [合格]
Fail [不合格]
ZFail [合格だが深度テスト不合格]
種類 | 意味 |
---|---|
Ref | ステンシル値。比較対象とされる値。 |
Comp | 比較関数。Equalなどいくつかの種類がある。 |
Pass | 合格時にステンシル値をどうするか。 |
Fail | 不合格時にステンシル値をどうするか。 |
ZFail | 合格だが深度テストが不合格だった場合にどうするか。 |
比較関数
比較関数は以下のものがあります。(ドキュメントから引用)
関数名 | 意味 |
---|---|
Greater | 参照値がバッファ値より大きい参照値のピクセルのみレンダリング |
GEqual | 参照値がバッファ値と等しいまたは大きい参照値のピクセルのみレンダリング |
Less | 参照値がバッファ値より小さい参照値のピクセルのみレンダリング |
LEqual | 参照値がバッファ値と等しいまたは小さい参照値のピクセルのみレンダリング |
Equal | 参照値がバッファ値と等しい参照値のピクセルのみレンダリング |
NotEqual | 参照値がバッファ値と等しくない参照値のピクセルのみレンダリング |
Always | 常にステンシル テストは成功 |
Never | 常にステンシル テストは失敗 |
処理
また、合格時などの処理については以下の項目があります。(ドキュメントから引用)
項目 | 意味 |
---|---|
Keep | バッファの現在コンテンツを保持します |
Zero | バッファにゼロを書き込みます |
Replace | 参照値をバッファに書き込みます |
IncrSat | バッファの現在値を増分させる。値がすでに 255 の場合は維持する |
DecrSat | バッファの現在値を減分させる。値がすでに 0 の場合は維持する |
Invert | すべてのビットを無効にする |
IncrWrap | バッファの現在値を増分する。値がすでに 255 の場合は 0 にする |
DecrWrap | バッファの現在値を減分する。値がすでに 0 の場合は 255 にする |