像素雾 (Direct3D 9)
像素雾从设备驱动程序中按像素计算的事实中获取其名称。 这不同于顶点雾,在转换和照明计算过程中由管道计算。 像素雾有时称为表雾,因为某些驱动程序使用预先计算的查找表来确定雾因子,使用每个像素的深度来应用混合计算。 可以使用由 D3DFOGMODE 枚举类型的成员标识的任何雾公式应用它。 这些公式的实现特定于驱动程序。 如果驱动程序不支持复杂的雾公式,它应降级为不太复杂的公式。
Eye-Relative 与基于 Z 的深度
为了缓解深度缓冲区中 z 值分布不均匀导致的与雾相关的图形项目,大多数硬件设备使用相对于眼睛的深度而不是基于 z 的像素雾深度值。 眼睛相对深度本质上是同质坐标集中的 w 元素。 Microsoft Direct3D 从设备空间坐标集中获取 RHW 元素的倒数,以重现 true w。 如果设备支持眼睛相对雾,则调用 IDirect3DDevice9::GetDeviceCaps 方法时,它会在 D3DCAPS9 结构的 RasterCaps 成员中设置 D3DPRASTERCAPS_WFOG 标志。 除了参考光栅器之外,软件设备始终使用 z 来计算像素雾效果。
当支持眼睛相对雾时,如果提供的投影矩阵在与设备空间中的 w 值等效,则系统会自动使用眼睛相对深度,而不是基于 z 的深度。 通过使用D3DTS_PROJECTION值并传递表示所需矩阵的 D3DMATRIX 结构,调用 IDirect3DDevice9::SetTransform 方法来设置投影矩阵。 如果投影矩阵不符合此要求,则雾效果未正确应用。 有关生成合规矩阵的详细信息,请参阅 投影转换(Direct3D 9)。
Direct3D 在其基于 w 的深度计算中使用当前设置的投影矩阵。 因此,应用程序必须设置合规的投影矩阵才能接收所需的基于 w 的功能,即使它不使用 Direct3D 转换管道也是如此。
Direct3D 检查投影矩阵的第四列。 如果系数为 [0,0,0,1] (对于相交投影),系统将对雾使用基于 z 的深度值。 在这种情况下,还必须指定设备空间中线性雾效果的开始和结束距离,范围从最接近点的 0.0 到用户,最远点为 1.0。
使用像素雾
使用以下步骤在应用程序中启用像素雾。
- 通过将D3DRS_FOGENABLE呈现状态设置为 true来启用雾混合。
- 在D3DRS_FOGCOLOR呈现状态中设置所需的雾色。
- 通过将D3DRS_FOGTABLEMODE呈现状态设置为 D3DFOGMODE 枚举类型的相应成员,选择要使用的雾公式。
- 在关联的呈现状态中,将雾化参数设置为所选雾模式所需的参数。 这包括线性雾的开始和结束距离,以及指数雾模式的雾密度。
以下示例演示了这些步骤在代码中的外观。
// 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 指针,然后取消引用它们。
相关主题