頂点の霧 (Direct3D 9)

システムが頂点の曇りを実行すると、ポリゴン内の各頂点に霧の計算が適用され、ラスタライズ中にポリゴンの面全体に結果が補間されます。 頂点の霧効果は、Direct3D 照明と変換エンジンによって計算されます。 詳細については、「 Fog パラメーター (Direct3D 9)」を参照してください。

変換と照明に Direct3D を使用しないアプリケーションでは、霧の計算を実行する必要があります。 この場合は、各頂点の反射色のアルファ 成分で計算される霧係数を配置します。 任意の数式 (範囲ベース、体積計算など) を自由に使用できます。 Direct3D では、指定された霧係数を使用して、各ポリゴンの面全体を補間します。 独自の変換と照明を実行するアプリケーションでは、独自の頂点霧計算も実行する必要があります。 その結果、このようなアプリケーションでは、霧ブレンドを有効にして、関連するレンダリング状態を通じて霧の色を設定するだけで済みます (「Fog Blending (Direct3D 9) 」および「 Fog Color (Direct3D 9)」の説明に従います。

Note

頂点シェーダーを使用する場合は、頂点の霧を使用する必要があります。 これを実現するには、頂点シェーダーを使用して、頂点ごとの霧の強度を oFog レジスタに書き込みます。 ピクセル シェーダーが完了すると、oFog データを使用して、霧の色で線形補間が行われます。 この強度は、ピクセル シェーダーでは使用できません。

 

Range-Basedの霧

Note

Direct3D では、Direct3D 変換と照明エンジンで頂点霧を使用する場合にのみ、範囲ベースの霧の計算が使用されます。 これは、ピクセル の霧がデバイス ドライバーに実装されており、ピクセル単位の範囲ベースの霧をサポートするハードウェアが現在存在しないためです。 アプリケーションが独自の変換と照明を実行する場合は、独自の霧計算(範囲ベースまたはそれ以外)を実行する必要があります。

 

場合によっては、霧を使用すると、オブジェクトが非直感的な方法で霧の色とブレンドされるグラフィックアーティファクトが発生することがあります。 たとえば、2 つの可視オブジェクトがあるシーンを想像してみてください。1 つは霧の影響を受けるほど遠く、もう 1 つは影響を受けないほど近い場所です。 表示領域が所定の位置に回転すると、オブジェクトが静止している場合でも、見かけ上の霧効果が変わる可能性があります。 次の図は、このような状況のトップダウン ビューを示しています。

diagram of two viewpoints and how they affect fog for two objects

範囲ベースの霧は、霧の効果を決定するための別の、より正確な方法です。 範囲ベースの霧では、Direct3D は、ビューポイントから頂点までの実際の距離を使用して、霧の計算を行います。 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 ポインターとしてキャストし、逆参照することで、データ変換なしでこれらのメソッドに浮動小数点値を正常に提供しています。

霧の種類