Cull サンプル

Cull サンプル

説明

このサンプルでは、オブジェクト境界ボックス (OBB) が視錐台の中にないオブジェクトをカリングする方法を示す。これらのオブジェクトを Microsoft® Direct3D® に渡さないことによって、表示されないこれらのオブジェクトのトランスフォームおよびライティングに Direct3D が費やす時間を節約できる。このようなオブジェクトがたくさんある場合や、これらのオブジェクトがたくさんの頂点を含む場合は、この時間の節約は非常に大きなものになり得る。

もっと複雑なカリングを効率的に行うには、オブジェクトの階層を作成し、オブジェクトのグループを囲む境界ボックスを使う。そうすることで、すべてのオブジェクトの OBB を視錐台と比較する必要がなくなる。

Direct3D で OBB をトランスフォームしてその結果のクリップ フラグをチェックするよりも、独自のコードでこの OBB と視錐台の交差の計算を行った方が効率的である。

このサンプル内のカリング ルーチンは、作成するプログラムのニーズに合わせて修正するとよい。

パス

ソース ファイル : (SDK ルート)\Samples\C++\Direct3D\Cull

実行可能ファイル : (SDK ルート)\Samples\C++\Direct3D\Bin

ユーザーズ ガイド

このプログラムを実行すると、ティーポットが 2 つのビューポートにレンダリングされたシーンが表示される。右側のビューポートでは、視錐台を使用してカリングが行われる。左側のビューポートには独立したカメラがあり、どこでカリングが行われるかがわかるように、右側のビューポートの視錐台が可視オブジェクトとして表示される。このシーンには 50 個のティーポットがランダムに配置されていて、半透明の OBB に沿ってレンダリングされる。

ティーポットは、カリング ステータスがわかるように、次のように色付けされている。

カラー 説明 カリング ステータス
濃い緑 オブジェクトが視錐台の内側にあることがすぐに確認された。 CS_INSIDE
明るい緑 オブジェクトが視錐台の内側にあることが、いくらかの作業を経て確認された。 CS_INSIDE_SLOW
濃い赤 オブジェクトが視錐台の外側にあることがすぐに確認された。 CS_OUTSIDE
明るい赤 オブジェクトが視錐台の外側にあることが、いくらかの作業を経て確認された。 CS_OUTSIDE_SLOW

右側のウィンドウに表示されるのは、緑色のティーポットだけである。ほとんどのティーポットは濃い緑か濃い赤である。これは、時間のかかるテストが必要なものは少なかったことを示している。

右側のビューポートのカメラを移動するには、ウィンドウの右側をクリックし、下に表示されているカメラ キーを使って移動する。

左側のビューポートのカメラを移動するには、ウィンドウの左側をクリックし、下に表示されているカメラ キーを使って移動する。

ティーポットを回転させて、視錐台に対する特定の関係をセットアップすることもできる。テーポットは移動できないが、視錐台を移動することによって同様のエフェクトを得られる。

次の表は、実装されているキーを示している。メニュー コマンドを使って同じ操作を行うことができる。

キー 動作
F1 ヘルプまたは使用可能なコマンドを表示する
F2 新しいレンダリング デバイスまたはディスプレイ モードを選択するようユーザーに指示する
Alt+Enter フルスクリーン モードとウィンドウ モードを切り替える
Esc アプリケーションを終了する
W、S、方向キー カメラを移動する
Q、E、A、Z カメラを回転する
Y、U、H、J ティーポットを回転する
N 左側のカメラを右側のカメラと同じ位置に移動する
M 右側のカメラを元の位置に移動する

プログラミング上の注意

このプログラムでは、次のような OBB と視錐台との交差アルゴリズムを使っている。

  1. OBB の角のポイントが 1 つでも視錐台の内側にあれば、CS_INSIDE を返す。
  2. その他の場合、OBB のすべての角のポイントが視錐台の 1 つの面の外側にあれば、CS_OUTSIDE を返す。
  3. その他の場合、視錐台のエッジが 1 つでも OBB の面を突き抜けていれば、CS_INSIDE_SLOW を返す。
  4. その他の場合、OBB のエッジが 1 つでも視錐台の面を突き抜けていれば、CS_INSIDE_SLOW を返す。
  5. その他の場合、視錐台内のポイントが 1 つでも OBB のすべての面の外側にあれば、CS_OUTSIDE_SLOW を返す。
  6. その他の場合、CS_INSIDE_SLOW を返す。

CS_INSIDE と CS_INSIDE_SLOW の違い、および CS_OUTSIDE と CS_OUTSIDE_SLOW の違いは、ここでは学習の目的でのみ示している。出荷用アプリケーションでは、通常は、OBB が視錐台の内側にあるのか外側にあるのかだけわかればよいので、CS_INSIDE および CS_OUTSIDE のみにカリング ステートを組み込むのが一般的である。

ここで示すカリング コードは、読みやすいように、余計な処理を含まない単純なコードになっている。パフォーマンスの最適化は行われていない。特に、境界ボックスが通常のボックス (たとえば、前面と背面が平行になっている) の場合は、追加の最適化処理を行うことができる。このアルゴリズムを一般化すれば、凸状の任意の形の境界を使って、中のモデルによりぴったりと合った境界に基づく処理ができるはずである。

このサンプルでは、ヘルパー関数などのプログラミング要素から構成される Microsoft DirectX® コードを使用する。このコードは DirectX ソフトウェア開発キット (SDK) の他のサンプルと共有されている。サンプル フレームワークのヘッダーは (SDK ルート)\Samples\C++\Common\Include、ソース コードは (SDK ルート)\Samples\C++\Common\Src にある。