像素雾 (Direct3D 9)

像素迷雾从以下事实中获取其名称:它是在设备驱动程序中按像素计算的。 这不同于顶点雾,后者在转换和照明计算过程中由管道计算。 像素雾有时称为表雾,因为某些驱动程序使用预计算的查找表来确定迷雾因子,并使用每个像素的深度应用于混合计算。 可以使用由 D3DFOGMODE 枚举类型的成员标识的任何迷雾公式应用它。 这些公式的实现特定于驱动程序。 如果驱动程序不支持复杂的迷雾公式,则应降级为不太复杂的公式。

Eye-Relative与基于 Z 的深度

为了缓解由于深度缓冲区中 z 值分布不均而导致的与迷雾相关的图形伪像,大多数硬件设备对像素迷雾使用眼部相对深度而不是基于 z 的深度值。 眼部相对深度实质上是同质坐标集中的 w 元素。 Microsoft Direct3D 从设备空间坐标集获取 RHW 元素的倒数,以重现 true w。 如果设备支持视线相对雾,则调用 IDirect3DDevice9::GetDeviceCaps 方法时,它会在 D3DCAPS9 结构的 RasterCaps 成员中设置D3DPRASTERCAPS_WFOG标志。 除了参考光栅器,软件设备始终使用 z 来计算像素雾效果。

当支持眼睛相对雾时,如果提供的投影矩阵在世界空间中生成与设备空间中的 w 值等效的 z 值,则系统会自动使用眼睛相对深度而不是基于 z 的深度。 可以通过调用 IDirect3DDevice9::SetTransform 方法、使用D3DTS_PROJECTION值并传递表示所需矩阵的 D3DMATRIX 结构来设置投影矩阵。 如果投影矩阵不符合此要求,则雾效果不会正确应用。 有关生成合规矩阵的详细信息,请参阅 投影转换 (Direct3D 9)

Direct3D 在其基于 w 的深度计算中使用当前设置的投影矩阵。 因此,应用程序必须设置一个合规的投影矩阵才能接收所需的基于 w 的特征,即使它不使用 Direct3D 转换管道也是如此。

Direct3D 检查投影矩阵的第四列。 如果系数为 [0,0,0,1] (的仿射投影) 系统将对雾使用基于 z 的深度值。 在这种情况下,还必须指定设备空间中线性雾效果的开始和结束距离,其范围从最靠近用户的 0.0 点和最远点的 1.0。

使用像素雾

使用以下步骤在应用程序中启用像素迷雾。

  1. 通过将D3DRS_FOGENABLE呈现状态设置为 TRUE 来启用迷雾混合。
  2. 在D3DRS_FOGCOLOR呈现状态下设置所需的雾色。
  3. 通过将D3DRS_FOGTABLEMODE呈现状态设置为 D3DFOGMODE 枚举类型的相应成员来选择要使用的迷雾公式。
  4. 在关联的呈现状态中,根据需要为所选迷雾模式设置迷雾参数。 这包括线性雾的开始和结束距离,以及指数雾模式的雾密度。

以下示例演示这些步骤在代码中的外观。

// 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 SetupPixelFog(DWORD Color, DWORD Mode)
{
    float Start   = 0.5f;    // For linear mode
    float End     = 0.8f;
    float Density = 0.66f;   // For exponential modes
 
    // Enable fog blending.
    g_pDevice->SetRenderState(D3DRS_FOGENABLE, TRUE);
 
    // Set the fog color.
    g_pDevice->SetRenderState(D3DRS_FOGCOLOR, Color);
    
    // Set fog parameters.
    if( Mode == D3DFOG_LINEAR )
    {
        g_pDevice->SetRenderState(D3DRS_FOGTABLEMODE, Mode);
        g_pDevice->SetRenderState(D3DRS_FOGSTART, *(DWORD *)(&Start));
        g_pDevice->SetRenderState(D3DRS_FOGEND,   *(DWORD *)(&End));
    }
    else
    {
        g_pDevice->SetRenderState(D3DRS_FOGTABLEMODE, Mode);
        g_pDevice->SetRenderState(D3DRS_FOGDENSITY, *(DWORD *)(&Density));
    }

某些迷雾参数需要作为浮点值,即使 IDirect3DDevice9::SetRenderState 方法只接受第二个参数中的 DWORD 值。 前面的示例将浮点值转换为 IDirect3DDevice9::SetRenderState ,无需进行数据转换,方法是将浮点变量的地址转换为 DWORD 指针,然后取消引用它们。

迷雾类型