ピクセル フォグ (Direct3D 9)
ピクセル フォグという名前は、デバイス ドライバーがピクセル単位で計算することに由来します。これは頂点フォグとは異なります。頂点フォグは、トランスフォームおよびライティングの計算時にパイプラインが計算します。ピクセル フォグは、ドライバーによっては、ブレンディング計算に適用するフォグ係数 (各ピクセルの深度を使用) を決定するために事前に計算された参照テーブルを使うため、テーブル フォグと呼ばれることもあります。ピクセル フォグは、D3DFOGMODE 列挙型のメンバーが示すフォグ公式のいずれかを使って適用します。これらの公式の実装はドライバー固有です。ドライバーが複雑なフォグ公式をサポートしていない場合は、より単純な公式を使う必要があります。
視点からの相対深度と Z ベースの深度
深度バッファー内での z 値の不均等なばらつきによって生じる、フォグの不自然なグラフィックス効果を抑えるために、ほとんどのハードウェア デバイスでは、ピクセル フォグに z ベース深度値ではなく視点からの相対深度を使います。視点からの相対深度とは、本質的には同次座標セットからの w 要素です。Microsoft Direct3D は、デバイス空間座標から RHW 要素の逆数を取得して真の w を再生成します。デバイスが視点からの相対フォグをサポートしている場合、IDirect3DDevice9::GetDeviceCaps メソッドを呼び出すと、そのデバイスは D3DCAPS9 構造体の RasterCaps メンバーに D3DPRASTERCAPS_WFOG フラグを設定します。リファレンス ラスタライザーを除き、ソフトウェア デバイスは常に z を使ってピクセル フォグ エフェクトを計算します。
視点との相対フォグがサポートされているとき、設定された射影行列でデバイス空間の w 値に対応する、ワールド空間の z 値を生成する場合、システムは z ベース深度よりも視点からの相対深度を優先して自動的に使います。射影行列を設定するには、IDirect3DDevice9::SetTransform メソッドを呼び出し、D3DTS_PROJECTION 値を使い、目的の行列を表す D3DMATRIX 構造体を渡します。射影行列がこの要件に対応していない場合、フォグ エフェクトは正しく適用されません。対応している行列の生成の詳細については、「射影トランスフォーム (Direct3D 9)」を参照してください。
Direct3D では、現在設定されている射影行列を使って w ベース深度の計算を実行します。したがって、Direct3D トランスフォーム パイプラインを使用しない場合であっても、アプリケーションでは、目的の w ベース機能を取得するために適切な射影行列を設定しておく必要があります。
Direct3D は射影行列の第 4 列を調べます。係数が [0,0,0,1] (アフィン射影) の場合には、システムは z ベースの深度値をフォグに使います。この場合、デバイス空間の線形フォグ エフェクトの開始距離および終了距離を指定する必要もあります。この範囲は、ユーザーに最も近いポイントを 0.0 とし、最も遠いポイントを 1.0 とした範囲です。
ピクセル フォグの使い方
アプリケーションでピクセル フォグを有効にするには、次の手順を実行します。
- D3DRS_FOGENABLE レンダリング ステートを TRUE に設定することによってフォグ ブレンディングを有効にします。
- D3DRS_FOGCOLOR レンダリング ステートで、任意のフォグ カラーを設定します。
- D3DRS_FOGVERTEXMODE レンダリング ステートを D3DFOGMODE 列挙型の対応するメンバーに設定して、使用するフォグ公式を選択します。
- 選択したフォグ モードで必要なフォグ パラメーターを関連するレンダリング ステートに設定します。線形フォグの開始距離と終了距離、指数フォグのフォグ密度も含みます。
次のコード例は、これらの手順を示しています。
// For brevity, error values in this example are not checked
// after each call. A real-world application should check
// these values appropriately.
//
// For the purposes of this example, g_pDevice is a valid
// pointer to an IDirect3DDevice9 interface.
void SetupPixelFog(DWORD Color, DWORD Mode)
{
float Start = 0.5f; // For linear mode
float End = 0.8f;
float Density = 0.66f; // For exponential modes
// Enable fog blending.
g_pDevice->SetRenderState(D3DRS_FOGENABLE, TRUE);
// Set the fog color.
g_pDevice->SetRenderState(D3DRS_FOGCOLOR, Color);
// Set fog parameters.
if( Mode == D3DFOG_LINEAR )
{
g_pDevice->SetRenderState(D3DRS_FOGTABLEMODE, Mode);
g_pDevice->SetRenderState(D3DRS_FOGSTART, *(DWORD *)(&Start));
g_pDevice->SetRenderState(D3DRS_FOGEND, *(DWORD *)(&End));
}
else
{
g_pDevice->SetRenderState(D3DRS_FOGTABLEMODE, Mode);
g_pDevice->SetRenderState(D3DRS_FOGDENSITY, *(DWORD *)(&Density));
}
IDirect3DDevice9::SetRenderState メソッドは、第 2 パラメーターに DWORD 値だけを受け取りますが、浮動小数点のフォグ パラメーターが要求されることもあります。前述の例では、浮動小数点の値をデータの平行移動なしで IDirect3DDevice9::SetRenderState に渡すために、浮動小数点変数のアドレスを DWORD ポインターとしてキャストし、次にそれを参照から解除しています。