Share via


頂点フォグ

頂点フォグ

システムは頂点フォグを実行するとき、ポリゴンの各頂点にフォグ計算を適用し、次に、ラスタライズの際、ポリゴンの面に結果を補間する。頂点フォグのエフェクトは、Microsoft® Direct3D® のライティング & トランスフォーム エンジンによって計算される。詳細については、「フォグ パラメータ」を参照すること。

アプリケーションで Direct3D を使わずにトランスフォーム & ライティングを実行する場合は、アプリケーションでフォグ計算を行う必要がある。この場合、計算されたフォグ係数を、各頂点のスペキュラ色のアルファ成分に置く。公式には、範囲ベースの公式、体積を利用する公式など、どのようなものでも使用できる。Direct3D は与えられたフォグ係数を使って、各ポリゴンの面を補間する。アプリケーションで独自のトランスフォーム & ライティングを実行する場合は、独自の頂点フォグの計算を実行する必要がある。したがって、そのようなアプリケーションでは、「フォグ ブレンディング」および「フォグ色」で説明するように、フォグ ブレンディングを有効にして、関連するレンダリング ステートによってフォグ色を設定するだけでよい。

  頂点シェーダを使う場合は、頂点フォグを使う必要がある。そのためには、頂点シェーダを使って、頂点ごとのフォグ強度を oFog レジスタに書き込む。ピクセル シェーダの処理が完了した後、oFog データを使ってフォグ色による線形補間が行われる。この強度はピクセル シェーダでは利用できない。

範囲ベースのフォグ

  Direct3D では、Direct3D のトランスフォーム & ライティング エンジンで頂点フォグを使うときのみ、範囲ベースのフォグの計算を実行する。これは、ピクセル フォグはデバイス ドライバに実装され、現在のところ、ピクセル単位の範囲ベースのフォグをサポートするハードウェアは存在しないためである。アプリケーションで独自のトランスフォーム & ライティングを実行する場合は、範囲ベースの計算かその他の計算による独自のフォグ計算を行う必要がある。

フォグを使うと、オブジェクトがフォグ色と直感的でない方法でブレンドされる不自然なグラフィックス効果が生じることがある。たとえば、2 つのオブジェクトが見えていて、一方はフォグの影響を受けるくらいに遠くにあり、他方は影響されないくらいに近くにあるというシーンを想定する。表示領域が同じ場所で回転した場合、オブジェクトが静止していたとしても、現れるフォグ エフェクトは変化することがある。次の図は、このような状況を上から見たところである。

視点の変更によるフォグへの影響

範囲ベースのフォグは、フォグ エフェクトをより正確に決定する方法である。範囲ベースのフォグでは、Direct3D は視点から頂点までの実際の距離をフォグの計算に使う。シーンの範囲内での頂点の深度ではなく 2 点間の距離の増加に従ってフォグのエフェクトが増加されるため、不自然な回転効果が回避される。

現在のデバイスが範囲ベースのフォグをサポートしている場合、IDirect3DDevice9::GetDeviceCaps メソッドを呼び出したときに、デバイスは D3DCAPS9 の RasterCaps メンバに D3DPRASTERCAPS_FOGRANGE 値を設定する。範囲ベースのフォグを有効にするには、D3DRS_RANGEFOGENABLE レンダリング ステートを TRUE に設定する。

範囲ベースのフォグは、Direct3D により、トランスフォーム & ライティングの間に計算される。Direct3D トランスフォーム & ライティング エンジンを使わないアプリケーションは、独自に頂点フォグの計算も行わなければならない。この場合、範囲ベースのフォグ係数を、各頂点のスペキュラ成分のアルファ成分に設定する。

頂点フォグの使い方

アプリケーションで頂点フォグを有効にするには、次の手順を実行する。

  1. D3DRS_FOGENABLE を TRUE に設定して、フォグ ブレンディングを有効にする。
  2. D3DRS_FOGCOLOR レンダリング ステートで、必要なフォグ色を設定する。
  3. D3DRS_FOGVERTEXMODE レンダリング ステートを D3DFOGMODE 列挙型のメンバに設定して、目的のフォグ公式を選択する。
  4. 選択したフォグ公式で必要なフォグ パラメータをレンダリング ステートに設定する。

次の C++ サンプル コードは、これらの手順を示している。

// 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 SetupVertexFog(DWORD Color, DWORD Mode, BOOL UseRange, FLOAT Density)
{
    float Start = 0.5f,    // Linear fog distances
          End   = 0.8f;
 
    // Enable fog blending.
    g_pDevice->SetRenderState(D3DRS_FOGENABLE, TRUE);
 
    // Set the fog color.
    g_pDevice->SetRenderState(D3DRS_FOGCOLOR, Color);
    
    // Set fog parameters.
    if(D3DFOG_LINEAR == Mode)
    {
        g_pDevice->SetRenderState(D3DRS_FOGVERTEXMODE, Mode);
        g_pDevice->SetRenderState(D3DRS_FOGSTART, *(DWORD *)(&Start;));
        g_pDevice->SetRenderState(D3DRS_FOGEND,   *(DWORD *)(&End;));
    }
    else
    {
        g_pDevice->SetRenderState(D3DRS_FOGVERTEXMODE, Mode);
        g_pDevice->SetRenderState(D3DRS_FOGDENSITY, *(DWORD *)(&Density;));
    }

    // Enable range-based fog if desired (only supported for
    //   vertex fog). For this example, it is assumed that UseRange
    //   is set to a nonzero value only if the driver exposes the 
    //   D3DPRASTERCAPS_FOGRANGE capability.
    // Note: This is slightly more performance intensive
    //   than non-range-based fog.
    if(UseRange)
        g_pDevice->SetRenderState(D3DRS_RANGEFOGENABLE, TRUE);
}

IDirect3DDevice9::SetRenderState メソッドは、第 2 引数に DWORD 値だけを受け取るが、浮動小数点のフォグ パラメータが要求されることもある。この例では、浮動小数点の値をデータの平行移動なしでメソッドに渡すために、浮動小数点変数のアドレスを DWORD ポインタとしてキャストし、次にそれを参照から解除している。