頂點霧 (Direct3D 9)

當系統執行頂點霧化時,它會在多邊形中的每個頂點套用霧計算,然後在點陣化期間將結果插補到多邊形的臉上。 頂點霧效果是由 Direct3D 光源和轉換引擎計算。 如需詳細資訊,請參閱 霧參數 (Direct3D 9)

如果您的應用程式不使用 Direct3D 進行轉換和光源,應用程式必須執行霧化計算。 在此情況下,請將霧因數放在每個頂點反射色彩的 Alpha 元件中。 您可以隨意使用您想要的任何公式 - 範圍型、磁碟區或其他。 Direct3D 使用提供的霧因數來插補每個多邊形的臉部。 執行自己轉換和光源的應用程式也必須執行自己的頂點霧化計算。 因此,這類應用程式只需要啟用霧混合,並透過相關聯的轉譯狀態設定霧色,如 霧混合(Direct3D 9)霧色(Direct3D 9)中所述。

注意

使用頂點著色器時,您必須使用頂點霧。 這可藉由使用頂點著色器將每個頂點霧度寫入 oFog 快取器來完成。 圖元著色器完成之後,oFog 數據會用來以線性方式插補霧色。 圖元著色器中無法使用這種強度。

 

Range-Based 霧

注意

Direct3D 只有在搭配 Direct3D 轉換和光源引擎使用頂點霧時,才會使用以範圍為基礎的霧計算。 這是因為圖元霧是在設備驅動器中實作,目前沒有硬體可支援以每像素範圍為基礎的霧。 如果您的應用程式執行自己的轉換和光源,它必須執行自己的霧計算、範圍型或其他方式。

 

有時候,使用霧可以引入圖形成品,使物件以非直覺的方式與霧色混合。 例如,想像一個場景,其中有兩個可見物件:一個足夠遠,可受到霧影響,另一個距離足以不受影響。 如果檢視區域就地旋轉,則明顯的霧效果可能會改變,即使對像是靜止的。 下圖顯示這類情況的由上至下檢視。

兩個觀點的圖表,以及它們如何影響兩個對象的霧

以範圍為基礎的霧是另一種更準確、更精確的霧效果判斷方式。 在以範圍為基礎的霧中,Direct3D 會使用從視點到頂點的實際距離來計算霧化。 Direct3D 會增加霧的影響,因為兩點之間的距離增加,而不是場景中頂點的深度,從而避免旋轉成品。

如果目前的裝置支援範圍型霧,當您呼叫 IDirect3DDevice9::GetDeviceCaps 方法時,它會在 D3DCAPS9 的 RasterCaps 成員中設定D3DPRASTERCAPS_FOGRANGE值。 若要啟用範圍型霧,請將D3DRS_RANGEFOGENABLE轉譯狀態設定為 TRUE

範圍型霧會在轉換和光源期間由 Direct3D 計算。 不使用 Direct3D 轉換和光源引擎的應用程式也必須執行自己的頂點霧化計算。 在此情況下,請為每個頂點提供反射元件的 Alpha 元件範圍型霧因數。

使用頂點霧

使用下列步驟在應用程式中啟用頂點霧。

  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 方法只接受第二個參數中的 DWORD 值,還是需要某些霧化參數作為浮點值。 此範例會藉由將浮點變數的位址轉換成 DWORD 指標,然後將浮點變數的位址轉換成 DWORD 指標,然後取值,以成功將這些方法提供浮點值給這些方法,而不需要數據轉譯。

霧類型