顶点雾 (Direct3D 9)
当系统执行顶点雾化时,它会在多边形中的每个顶点处应用迷雾计算,然后在光栅化期间将结果内插到多边形的面上。 顶点雾效果由 Direct3D 照明和转换引擎计算。 有关详细信息,请参阅 Fog Parameters (Direct3D 9) 。
如果应用程序不使用 Direct3D 进行转换和照明,则应用程序必须执行雾计算。 在这种情况下,将每个顶点的反射颜色的 alpha 分量中计算的雾因子放置。 你可以随意使用所需的任何公式 - 基于范围、体积或其他公式。 Direct3D 使用提供的雾因子在每个多边形的面上内插。 执行自己的转换和照明的应用程序还必须执行自己的顶点雾计算。 因此,此类应用程序只需启用雾混合并通过关联的呈现状态设置雾色,如 “雾混合 (Direct3D 9) 和 雾色 (Direct3D 9) 中所述。
注意
使用顶点着色器时,必须使用顶点雾。 这是通过使用顶点着色器将每个顶点雾强度写入 oFog 寄存器来实现的。 像素着色器完成后,oFog 数据用于与雾色进行线性内插。 此强度在像素着色器中不可用。
Range-Based雾
注意
Direct3D 仅在将顶点雾与 Direct3D 转换和照明引擎配合使用时,才使用基于范围的雾计算。 这是因为像素雾是在设备驱动程序中实现的,目前不存在支持基于每个像素范围的雾的硬件。 如果应用程序执行自己的转换和照明,它必须执行自己的雾计算,基于范围或其他。
有时,使用雾可能会引入图形伪像,导致对象以非直观方式与雾色混合。 例如,假设场景中有两个可见对象:一个距离足够远,可受雾影响,另一个距离足够近,不受影响。 如果观看区域就地旋转,则明显的雾效果可能会改变,即使对象是静止的。 下图显示了这种情况的自上而下视图。
基于范围的雾是确定雾效果的另一种更准确的方法。 在基于范围的雾中,Direct3D 使用从视点到顶点的实际距离进行雾计算。 Direct3D 会随着两点之间的距离的增加而增加雾的效果,而不是场景中顶点的深度,从而避免旋转伪像。
如果当前设备支持基于范围的雾,则调用 IDirect3DDDevice9::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 指针,然后取消引用,成功为这些方法提供浮点值,而无需进行数据转换。
相关主题