プロジェクション変換 (Direct3D 9)
投影変換は、カメラの内部を制御していると考えることができます。カメラ用のレンズを選ぶのに似ています。 これは、3 つの変換の種類の中で最も複雑です。 このプロジェクション変換の説明は、次のトピックにまとめられます。
投影マトリックスは、通常、スケールと遠近投影です。 投影変換は、視錐台を直方体形状に変換します。 視錐台の近端は遠端よりも小さいため、カメラに近いオブジェクトを拡張する効果があります。これは、パースペクティブをシーンに適用する方法です。
表示錐台 では、カメラと表示変換空間の原点の間の距離は D として任意に定義されるため、投影マトリックスは次の図のようになります。
投影行列図
表示マトリックスは、z 方向に - D で平行移動することで、カメラを原点に変換します。翻訳行列は次の図のようになります。
の図
次の図に示すように、平行移動行列に射影行列 (T*P) を乗算すると、複合投影行列が得られます。
複合投影行列図
パースペクティブ変換は、視錐台を新しい座標空間に変換します。 次の図に示すように、錐台が直方体になり、原点がシーンの右上隅から中央に移動していることに注意してください。
パースペクティブ変換では、x 方向と y 方向の制限が -1 と 1 です。 z 方向の制限は、前面平面の場合は 0、背面平面の場合は 1 です。
この行列は、カメラからニアクリッピング平面への指定された距離に基づいてオブジェクトを平行移動およびスケーリングしますが、視野 (fov) は考慮せず、距離内のオブジェクトに対して生成される z 値はほぼ同じになり、深度比較が困難になります。 次のマトリックスは、これらの問題に対処し、ビューポートの縦横比を考慮して頂点を調整するため、遠近投影に適しています。
のマトリックスの図
この行列では、Znはニアクリッピング平面のz値である。 変数 w、h、Q には次の意味があります。 fovw と fovk は、ビューポートの水平および垂直のビュー フィールドをラジアンで表します。
変数の意味の式を
アプリケーションでは、視野角度を使用して x と y のスケーリング係数を定義すると、ビューポートの水平寸法と垂直寸法 (カメラ空間) を使用する場合ほど便利ではない場合があります。 次の w と h の 2 つの数式は、算術演算でビューポートの寸法を使用し、前の数式と同じになります。
これらの数式では、Zn はニア クリッピング平面の位置を表し、Vw 変数と Vh 変数は、ビューポートの幅と高さをカメラ空間で表します。
C++ アプリケーションの場合、これら 2 つのディメンションは、D3DVIEWPORT9 構造体の Width メンバーと Height メンバーに直接対応します。
どの数式を使用する場合でも、カメラに非常に近い z 値は大きく異なるため、Zn をできるだけ大きな値に設定してください。 これにより、16 ビット z バッファーを使用した深度比較がやや複雑になります。
ワールド変換とビュー変換と同様に、IDirect3DDevice9::SetTransform メソッドを呼び出してプロジェクション変換を設定します。
プロジェクション マトリックスの設定
次の ProjectionMatrix サンプル関数は、前面と背面のクリッピング平面と、水平および垂直の画角フィールドを設定します。 ビューのフィールドは pi ラジアン未満にする必要があります。
D3DXMATRIX
ProjectionMatrix(const float near_plane, // Distance to near clipping
// plane
const float far_plane, // Distance to far clipping
// plane
const float fov_horiz, // Horizontal field of view
// angle, in radians
const float fov_vert) // Vertical field of view
// angle, in radians
{
float h, w, Q;
w = (float)1/tan(fov_horiz*0.5); // 1/tan(x) == cot(x)
h = (float)1/tan(fov_vert*0.5); // 1/tan(x) == cot(x)
Q = far_plane/(far_plane - near_plane);
D3DXMATRIX ret;
ZeroMemory(&ret, sizeof(ret));
ret(0, 0) = w;
ret(1, 1) = h;
ret(2, 2) = Q;
ret(3, 2) = -Q*near_plane;
ret(2, 3) = 1;
return ret;
} // End of ProjectionMatrix
マトリックスを作成した後、D3DTS_PROJECTIONを指定 IDirect3DDevice9::SetTransform で設定します。
D3DX ユーティリティ ライブラリには、プロジェクション マトリックスの設定に役立つ次の関数が用意されています。
- D3DXMatrixPerspectiveLH
- D3DXMatrixPerspectiveRH
- D3DXMatrixPerspectiveFovLH
- D3DXMatrixPerspectiveFovRH
- D3DXMatrixPerspectiveOffCenterLH
- D3DXMatrixPerspectiveOffCenterRH
W フレンドリなプロジェクション マトリックス
Direct3D では、ワールド、ビュー、プロジェクション マトリックスによって変換された頂点の w 成分を使用して、深度バッファーまたは霧の効果で深度ベースの計算を実行できます。 このような計算では、プロジェクション 行列が w をワールド空間 z と等価に正規化する必要があります。 つまり、投影行列に 1 以外の (3,4) 係数が含まれている場合は、すべての係数を (3,4) 係数の逆数でスケーリングして、適切な行列を作成する必要があります。 準拠したマトリックスを指定しないと、霧効果と深度バッファリングが正しく適用されません。
次の図は、非準拠の投影マトリックスを示し、同じマトリックスをスケールして、目の相対霧が有効になるようにします。
非準拠の投影行列と、視線相対霧図
上記の行列では、すべての変数は 0 以外と見なされます。 視線相対霧の詳細については、「Eye-Relative と Z ベースの深度」を参照してください。 w ベースの深度バッファリングの詳細については、「深度バッファー (Direct3D 9)を参照してください。
Direct3D では、w ベースの深度計算で現在設定されているプロジェクション マトリックスが使用されます。 その結果、変換に Direct3D を使用しない場合でも、アプリケーションは、必要な w ベースの機能を受け取るように準拠したプロジェクション マトリックスを設定する必要があります。
関連トピック