ステンシル バッファー は、特殊効果を生成するために、イメージ内のピクセルをマスクするために使用されます。 マスクは、ピクセルを描画するかどうかを制御します。 これらの特殊効果には、合成、デカール化、ディゾルブ、フェード、スワイプ、輪郭とシルエット、両面ステンシルが含まれます。 より一般的な効果の一部を以下に示します。
ステンシル バッファーは、レンダリング ターゲット サーフェスへの描画をピクセル単位で有効または無効にします。 最も基本的なレベルでは、アプリケーションでレンダリングされたイメージのセクションをマスクして、表示されないようにすることができます。 多くの場合、アプリケーションでは、ディゾルブ、デカール、アウトラインなどの特殊効果にステンシル バッファーが使用されます。
ステンシル バッファー情報は、z バッファー データに埋め込まれます。
ステンシル バッファーのしくみ
Direct3D は、ステンシル バッファーの内容に対してピクセル単位でテストを実行します。 ターゲット サーフェス内の各ピクセルについて、ステンシル バッファー内の対応する値、ステンシル参照値、およびステンシル マスク値を使用してテストを実行します。 テストに合格すると、Direct3D はアクションを実行します。 テストは、次の手順を使用して実行されます。
- ステンシル マスクを使用してステンシル参照値のビットごとの AND 演算を実行します。
- ステンシル マスクを使用して、現在のピクセルのステンシル バッファー値のビットごとの AND 演算を実行します。
- 比較関数を使用して、ステップ 1 の結果をステップ 2 の結果と比較します。
上記の手順は、次のコード行に示されています。
(StencilRef & StencilMask) CompFunc (StencilBufferValue & StencilMask)
- StencilRef はステンシル参照値を表します。
- StencilMask は、ステンシル マスクの値を表します。
- CompFunc は比較関数です。
- StencilBufferValue は、現在のピクセルのステンシル バッファーの内容です。
- アンパサンド (> 記号) は、ビットごとの AND 演算を表します。
ステンシル テストに合格すると、現在のピクセルがターゲット サーフェスに書き込まれ、それ以外の場合は無視されます。 既定の比較動作では、各ビットごとの演算が判明した場合でも、ピクセルを書き込みます。この動作を変更するには、列挙型の値を変更して、目的の比較関数を識別します。
アプリケーションでは、ステンシル バッファーの操作をカスタマイズできます。 比較関数、ステンシル マスク、ステンシル参照値を設定できます。 ステンシル テストが成功または失敗したときに Direct3D が実行するアクションを制御することもできます。
合成
アプリケーションでは、ステンシル バッファーを使用して、2D または 3D イメージを 3D シーンに合成できます。 ステンシル バッファー内のマスクは、レンダリング ターゲット サーフェスの領域を隠すために使用されます。 保存された 2D 情報 (テキストやビットマップなど) は、隠れた領域に書き込むことができます。 または、アプリケーションで、レンダリング ターゲット サーフェスのステンシル マスク領域に追加の 3D プリミティブをレンダリングすることもできます。 シーン全体をレンダリングすることもできます。
多くの場合、ゲームは複数の 3D シーンを合成します。 たとえば、ゲームを運転すると、通常、リアビュー ミラーが表示されます。 ミラーには、ドライバーの背後にある 3D シーンのビューが含まれています。 これは基本的に、ドライバーの前方ビューと合成された 2 番目の 3D シーンです。
デカールを貼る
Direct3D アプリケーションでは、デカル処理を使用して、レンダリング ターゲット サーフェスに描画される特定のプリミティブ イメージのピクセルを制御します。 アプリケーションでは、プリミティブのイメージにデカールを適用して、同一平面ポリゴンを正しくレンダリングできるようにします。
たとえば、道路にタイヤ マークと黄色の線を適用する場合、マーキングは道路の上に直接表示されます。 ただし、マーキングと道路の z 値は同じです。 したがって、深度バッファーでは、2 つの間にクリーンな分離が生成されない場合があります。 背面プリミティブの一部のピクセルは、フロント プリミティブの上にレンダリングされ、その逆も可能です。 結果として得られる画像は、フレーム間で輝いているように見えます。 この効果は、zファイティング または フリッカリングと呼ばれます。
この問題を解決するには、ステンシルを使用して、デカールが表示される背面プリミティブのセクションをマスクします。 z バッファリングをオフにし、フロント プリミティブのイメージをレンダー ターゲット サーフェスのマスクされた領域にレンダリングします。
複数のテクスチャ ブレンドを使用してこの問題を解決できますが、これを行うと、アプリケーションで生成できるその他の特殊効果の数が制限されます。 ステンシル バッファーを使用してデカールを適用すると、テクスチャ ブレンド ステージが解放され、他の効果が得られます。
ディゾルブ、フェード、スワイプ
アプリケーションでは、ディゾルブ、スワイプ、フェードなど、映画やビデオでよく使用される特殊効果がますます使用されています。
ディゾルブでは、1 つの画像がスムーズなフレームシーケンスで徐々に別のイメージに置き換えられます。 Direct3D には複数のテクスチャ ブレンドを使用して同じ効果を実現する方法が用意されていますが、ディゾルブにステンシル バッファーを使用するアプリケーションでは、ディゾルブ中に他の効果にテクスチャ ブレンド機能を使用できます。
アプリケーションがディゾルブを実行するときは、2 つの異なるイメージをレンダリングする必要があります。 ステンシル バッファーを使用して、各イメージのどのピクセルをレンダリング ターゲット サーフェイスに描画するかを制御します。 一連のステンシル マスクを定義し、連続するフレームのステンシル バッファーにコピーすることができます。 または、最初のフレームのベース ステンシル マスクを定義し、増分的に変更することもできます。
ディゾルブの開始時に、開始イメージのほとんどのピクセルがステンシル テストに合格するように、ステンシル関数とステンシル マスクがアプリケーションによって設定されます。 終了イメージのほとんどのピクセルは、ステンシル テストに失敗します。 連続するフレームにおいて、ステンシルマスクは更新され、開始イメージ内の徐々に少ないピクセルがテストを通過するようになります。 フレームが進行すると、終了イメージ内のピクセルの数が少なくなり、テストに失敗します。 この方法では、任意のディゾルブ パターンを使用して、アプリケーションでディゾルブを実行できます。
フェードインまたはフェードアウトは、溶解の特別なケースです。 フェードインの際、ステンシルバッファーを使用して、黒または白のイメージから3Dシーンのレンダリングに溶け込んでいきます。 フェードアウトは逆で、アプリケーションは 3D シーンのレンダリングから始まり、黒または白にディゾルブされます。 フェードは、使用したい任意のパターンを使用して行うことができます。
Direct3D アプリケーションでは、スワイプにも同様の手法が使用されます。 たとえば、アプリケーションが左から右へのスワイプを実行すると、終了画像が左から右に開始イメージの上に徐々にスライドするように表示されます。 ディゾルブと同様に、連続するフレームのステンシル バッファーに読み込まれる一連のステンシル マスクを定義するか、開始ステンシル マスクを連続して変更する必要があります。 ステンシル マスクは、開始イメージからのピクセルの書き込みを無効にし、終了イメージからのピクセルの書き込みを有効にするために使用されます。
スワイプは、アプリケーションがスワイプの逆の順序で終了画像からピクセルを読み取る必要がある点で、ディゾルブよりもやや複雑です。 つまり、スワイプが左から右に移動する場合、アプリケーションは終了画像から右から左にピクセルを読み取る必要があります。
輪郭とシルエット
ステンシル バッファーを使用すると、アウトラインや silhouetting などのより抽象的な効果を得ることができます。
アプリケーションで、同じ図形の少し小さいプリミティブのイメージにステンシル マスクを適用する場合、結果のイメージにはプリミティブのアウトラインのみが含まれます。 その後、アプリケーションはイメージのステンシル マスク領域を単色で塗りつぶし、プリミティブに浮き出しの外観を与えることができます。
ステンシル マスクがレンダリングするプリミティブと同じサイズと形状の場合、結果のイメージにはプリミティブがあるべき場所に穴が含まれます。 その後、アプリケーションは穴を黒で埋め、プリミティブのシルエットを生成できます。
両面ステンシル
シャドウ ボリュームは、ステンシル バッファーを使用してシャドウを描画するために使用されます。 アプリケーションは、遮蔽するジオメトリによって投影されたシャドウボリュームを計算するために、シルエットエッジを計算し、それらを光源から離れて押し出して3Dボリュームのセットにします。 その後、これらのボリュームはステンシル バッファーに 2 回レンダリングされます。
最初のレンダリングでは、前方向きの多角形が描画され、ステンシル バッファーの値がインクリメントされます。 2 番目のレンダーでは、シャドウ ボリュームの裏側のポリゴンを描画し、ステンシル バッファーの値を減少させます。 通常、インクリメントされた値とデクリメントされた値はすべて、互いに取り消されます。ただし、シーンは既に通常のジオメトリでレンダリングされているため、シャドウ ボリュームがレンダリングされるときに、一部のピクセルが z バッファー テストに失敗します。 ステンシル バッファーに残っている値は、シャドウ内のピクセルに対応します。 これらの残りのステンシルバッファーの内容がマスクとして使用され、大きく広がる黒い四角形がシーン全体にアルファブレンドされます。 ステンシル バッファーがマスクとして機能すると、シャドウ内のピクセルが暗くなります。
つまり、シャドウ ジオメトリは光源ごとに 2 回描画されるため、GPU の頂点スループットが低下します。 両面ステンシル機能は、この状況を軽減するように設計されています。 この方法では、ステンシル状態の 2 つのセット (下の名前) があり、1 つは前面の三角形にそれぞれ設定され、もう 1 つは背面の三角形に対して設定されます。 この方法では、シャドウ ボリュームごとに、ライトごとに 1 つのパスのみが描画されます。
関連トピック