顶点雾 (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 分量中的基于范围的雾因子。
使用顶点雾
使用以下步骤在应用程序中启用顶点雾。
- 通过将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 指针,然后取消引用这些方法,从而成功地将这些方法提供浮点值,而无需进行数据转换。
相关主题