頂點水 (Direct3D 9)
當系統執行頂點模糊時,它會在多邊形中的每個頂點套用模糊計算,然後在點陣化期間將結果插補到多邊形的臉部。 頂點模糊效果是由 Direct3D 光源和轉換引擎計算。 如需詳細資訊,請參閱 (Direct3D 9) 。
如果您的應用程式未使用 Direct3D 進行轉換和光源,應用程式必須執行模糊計算。 在此情況下,請將每一個頂點的反射色彩 Alpha 元件中計算的模糊因數。 您可以隨意使用您想要的任何公式- 範圍型、磁片區或其他。 Direct3D 使用提供的模糊因數來插補每個多邊形的臉部。 執行自己的轉換和光源的應用程式也必須執行自己的頂點模糊計算。 因此,這類應用程式只需要啟用模糊混合,並透過相關聯的轉譯狀態設定水氣色彩,如 「模糊混合」 (Direct3D 9) 和 「模糊色彩」 (Direct3D 9) 中所述。
注意
使用頂點著色器時,您必須使用頂點模糊。 這可藉由使用頂點著色器將個別頂點的濃度寫入 oFog 暫存器來完成。 圖元著色器完成之後,oFog 資料會用來以模糊色彩線性插補。 圖元著色器不提供此濃度。
注意
Direct3D 只有在搭配 Direct3D 轉換和光源引擎使用頂點模糊時,才會使用以範圍為基礎的模糊計算。 這是因為圖元模糊是在設備磁碟機中實作,目前沒有硬體可支援每個圖元範圍型的模糊。 如果您的應用程式執行自己的轉換和光源,它必須執行自己的模糊計算、範圍型或其他。
有時候,使用水氣可能會引入導致物件以非直覺方式與水氣色彩混合的圖形成品。 例如,想像一個場景,其中有兩個可見物件:一個遠到足以受到水氣影響,另一個距離足以不受影響。 如果檢視區域就地旋轉,即使物件是固定的,明顯的模糊效果也會變更。 下圖顯示這類情況的由上而下檢視。
以範圍為基礎的水氣是另一個更精確的方式,可用來判斷水氣效果。 在以範圍為基礎的模糊中,Direct3D 會使用從觀點到頂點的實際距離,進行其模糊計算。 Direct3D 會隨著兩點之間的距離增加而增加,而不是場景中頂點的深度,進而避免旋轉成品。
如果目前的裝置支援以範圍為基礎的模糊,當您呼叫IDirect3DDevice9::GetDeviceCaps方法時,它會在D3DCAPS9 的 RasterCaps成員中設定D3DPRASTERCAPS_FOGRANGE值。 若要啟用以範圍為基礎的模糊,請將D3DRS_RANGEFOGENABLE轉譯狀態設定為 TRUE。
在轉換和光源期間,Direct3D 會計算以範圍為基礎的模糊。 不使用 Direct3D 轉換和光源引擎的應用程式也必須執行自己的頂點模糊計算。 在此情況下,請針對每個頂點,在反射元件的 Alpha 元件中提供範圍型的模糊因數。
使用下列步驟在應用程式中啟用頂點模糊。
- 將D3DRS_FOGENABLE設定為 TRUE來啟用水氣混合。
- 設定D3DRS_FOGCOLOR轉譯狀態的水氣色彩。
- 將D3DRS_FOGVERTEXMODE轉譯狀態設定為 D3DFOGMODE 列舉型別的成員,以選擇所需的模糊公式。
- 針對轉譯狀態中選取的模糊公式,將模糊參數設定為所需。
下列以 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 指標,然後將浮點值轉譯為這些方法成功提供浮點值。