Pixel Fog

Pixel fog gets its name from the fact that it is calculated on a per-pixel basis in the device driver. This is different from vertex fog, which is computed by the pipeline during transformation and lighting calculations. Pixel fog is sometimes called table fog because some drivers use a precalculated lookup table to determine the fog factor, using the depth of each pixel to apply in blending computations. It can be applied using any fog formula identified by members of the FogMode enumerated type. The implementations of these formulas are driver-specific. If a driver does not support a complex fog formula, it should degrade to a less complex formula.

Eye-Relative vs. Z-Based Depth

To alleviate fog-related graphic artifacts caused by uneven distribution of z-values in a depth buffer, most hardware devices use eye-relative depth instead of z-based depth values for pixel fog. Eye-relative depth is essentially the w element from a homogeneous coordinate set. Microsoft Direct3D takes the reciprocal of the RHW element from a device space coordinate set to reproduce true w. If a device supports eye-relative fog, it sets the SupportsWFog property in the RasterCaps member of the Caps structure that is returned by a call to Manager.GetDeviceCaps. With the exception of the reference rasterizer, software devices always use z to calculate pixel fog effects.

When eye-relative fog is supported, the system automatically uses eye-relative depth rather than z-based depth if the provided projection matrix produces z-values in world space that are equivalent to w-values in device space. Set the projection matrix by calling the Device.SetTransform method, using the TransformType.Projection value and passing a Matrix structure that represents the desired matrix. If the projection matrix is not compliant with this requirement, fog effects are not applied properly. For details about producing a compliant matrix, see A W-Friendly Projection Matrix. The perspective projection matrix provided in What Is the Projection Transformation? produces a compliant projection matrix.

Direct3D uses the currently set projection matrix in its w-based depth calculations. As a result, an application must set a compliant projection matrix to receive the desired w-based features, even if it does not use the Direct3D transformation pipeline.

Direct3D checks the fourth column of the projection matrix. If the coefficients are [0,0,0,1] (for an affine projection) the system uses z-based depth values for fog. In this case, the start and end distances for linear fog effects must be specified in device space, which ranges from 0.0 at the nearest point to the user, and 1.0 at the farthest point.

Using Pixel Fog

Use the following steps to enable pixel fog in an application.

  1. Enable fog blending by setting the RenderStateManager.FogEnable property to true.
  2. Set the desired fog color in the RenderStateManager.FogColor property.
  3. Choose the fog formula to use by setting the RenderStateManager.FogTableMode property to the corresponding member of the FogMode enumerated type.
  4. Set the fog parameters as desired for the selected fog mode in the associated render states. This includes the start and end distances for linear fog, and fog density for exponential fog mode.

The following C# code example shows what these steps might look like in code.

          [C#]
          

// For the purposes of this example, device is a valid Device object.
//
void SetupPixelFog(Color color, FogMode mode)
{
    float Start   = 0.5f;   // For linear mode.
    float End     = 0.8f;   //

    float Density = 0.66f;  // For exponential modes.

    // Enable fog blending.
    device.RenderState.FogEnable = true;

    // Set the fog color.
    device.RenderState.FogColor = color;

    // Set fog parameters.
    if (mode == FogMode.Linear)
    {
        device.RenderState.FogTableMode = mode;
        device.RenderState.FogStart = Start;
        device.RenderState.FogEnd = End;
    }
    else
    {
        device.RenderState.FogTableMode = mode;
        device.RenderState.FogDensity = Density;
    }
}