Depth Bounds Test(1)

Depth Bounds Testは、GeForce FX(NV35)以降のNVIDIAのGPUでサポートされている機能です。

Depth Bounds Testの機能

この機能は、深度値が指定の範囲に入っているかどうかをテストし、範囲内ならばピクセルシェーダーを動作させ、範囲外ならば該当ピクセルを早期棄却します。この場合の深度値は、デプスバッファの該当ピクセルの位置に、既に格納されている深度値が使用されます。したがって、描画されているプリミティブの深度値は関係ありません。この点は、他の深度テストやアルファテストと異なります。

この機能は、元来stencil shadow volumeの最適化のために導入されました。オリジナルのアイデアとしては、scissorテストがviewportを矩形にテストし、明らかに処理が不要なピクセルを早期棄却するのと同様に、Depth Bounds Testが深度方向のテストを行い、明らかに処理が不要なピクセルを早期棄却し、結果として実行されるピクセルシェーダー数を最適化しようとするものでした。また、未確認ですが、AMDのsouthern isaland世代のGPUでこの機能が導入されている旨が記載されている資料があります(AMDのPRTに関する資料でDepth Bounds Testと表記されている)。将来的には、NVIDIA,AMD双方のGPU上で使用できる機能となるかもしれません。

Depth Bounds Testの使い道

上記のとおり、Depth Bounds Testは、元来stencil shadow volumeのために導入されましたが、現在では他のレンダリング技法の中でも、使える箇所がいくつかあります。

  • Deferred Renderingにおけるライトのaccumulation
  • Deferred RenderingにおけるCascaded Shadow Map
  • 被写界深度エフェクト
  • 遠景描画

これらについて考えてみたいと思います。

Deferred Renderingにおけるライトのaccumulation

DeferredRenderingを行う際に、ローカルライト(一般的に効果範囲が狭く、数の多いライト)を適用する場合を考えます。G-Bufferは既に描画済みとします。ライトの適用範囲をあらわす、sphere(Point light)もしくはcone(Spot light)を描画し、起動したピクセルシェーダーは、該当位置のG-bufferに関するシェーディングを行い、accumulationバッファに加算していく手法があります。この方法は、Compute Shaderが無いDX9世代のGPUで動作しますが、問題点がいくつかあります。
まず、深度テストを用いるのが難しいです。裏面カリングを行い、深度テストを用いると、ライトの効果範囲を正しく描画できる上に、手前にある壁などで明らかに遮蔽されている場合は、ピクセルを棄却することが出来ます。しかし、ローカルライトのプリミティブの体積内にカメラが入ると、ライトの効果範囲のピクセルは一切描画されません。裏面カリングを行わない状態では、ピクセルシェーダーが同一ピクセルで2回起動するケースが発生します。深度テストを行わなければ、すべての場合でピクセルシェーダーが起動され、描画は正しく行われますが、手前に壁などがあり、明らかに処理する必要の無いローカルライトでも、ピクセルシェーダーが起動してしまいます。

このケースで、Depth Bounds Testを活用すると、効率的に、処理する必要の無いピクセルを棄却することが出来ます。具体的にには、ローカルライトの効果範囲、たとえばPoint lightならば、その直径に相当する範囲をDepth Bounds Testに設定することで、その範囲のピクセルのみをパスするように設定します。この様にすることで、ライトが届く可能性のあるピクセルのみ、ピクセルシェーダーが起動するようになります。

具体的な例のスクリーンショットになります。この例では、ローカルライトとして、Point lightを5個配置してあります。

次に示すのは、Depth Bounds Testを行わずに、Point lightのaccumulationを行った場合に、ピクセルシェーダーが起動した場所を赤く加算ブレンディング行ったものです。

次に示すのは、Depth Bounds Testを行って、ローカルライトの範囲外ピクセルを棄却したものです。Depth Bounds Testによって、起動されるピクセルシェーダー数が劇的に削減されるのがわかると思います。

Deferred RenderingにおけるCascaded Shadow Map

これは、Deferred Renderingというよりも、Depth pre-passが実行されている状況ならば適用可能です。Cascaded Shadow Mapは、カメラからの深度に応じて、適用するShadow Mapを切り替えることで、視点から近い位置では解像度を保ちつつも、広範囲にShadow Mapを適用する手法です。

この、適用するShadow Mapの切り替えを、ピクセルシェーダー内の分岐で行わず、Depth Bounds Testで行います。このようにすることで、ピクセルシェーダー内の分岐が避けられるうえに、同時に参照されるShadow Mapのテクスチャが1つになるので、テクスチャキャッシュのヒット率も向上します。Cascaded Shadow Mapのレイヤー数に応じて、複数回プリミティブを描画しなければならないですが、描画するプリミティブは、Full-screen Quadなので問題になりません。現在のGPUは明らかに処理が不要はピクセルは高速に棄却するので、棄却されるピクセルのコストもほとんど無視できます。Cascaded Shadow Mapの切り替え位置で、線形補完などを行っているケースでは、補完を適用する範囲で、さらに別のシェーダーを用意して、描画を行います。

被写界深度エフェクト

現在もっとも一般的な被写界深度エフェクトは、レンダリング結果から何らか技法を用いて縮小バッファを作成して、それを深度値に応じて適用する手法だと思われます。いわゆる”前ボケのかぶり”がない技法を用いている場合、被写界深度内のピクセルはそのままで、値の変更がないはずです。この範囲がスクリーンのピクセルに占める割合によって、Depth Bounds Testを適用するべきかどうかは変わってくると思うのですが、一般的にゲームが動作している状況では、浅い被写界深度はあまり用いないと思われます。Depth Bounds Testで被写界深度を含めて手前のピクセルを棄却して、被写界深度の奥側のピクセルにDOFを適用し、次の描画で、被写界深度を含めて奥側のピクセルを棄却して、手前側のDOFを適用します。この様にすることで、処理するピクセル数を削減することが出来ます。また、被写界深度の手前をボカさないケースでは、2度目のパスは必要なくなります。

遠景描画

一般的なゲームのアウトドアシーンでは、最も遠い部分の描画を、天球に相当するオブジェクトで描画するケースがあると思います。スクリーンスペースでさまざまな描画エフェクトを行う場合、この遠景部分を処理する必要の無いケースでは、Depth Bounds Testで該当部分のピクセルシェーダーを棄却することが出来ます。

次回はDirectXにおける、Depth Bounds Testの設定方法と、設定にかかるコストを考えてみます。

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中