頂点の霧 (Direct3D 9)

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

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

注意

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

 

Range-Based霧

注意

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

 

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

2 つの視点の図と、2 つのオブジェクトの霧に与える影響

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

霧の種類