Pixel Fog

[Previous] [Next]

Vertex fog is widely supported by 3D hardware, and this type of fog works well in most cases. It causes problems, however, when large polygons are used. If one vertex is extremely close to the camera and another is somewhere in the fog, the fog linearly interpolates between those two vertices, which is probably very different from what the fog equation would generate if applied at each pixel. To provide more accurate fog for such situations, Direct3D supports pixel fog. Pixel fog in Direct3D is calculated on a per-pixel basis in the device. Pixel fog is also known as table fog since some devices use a precalculated lookup table to determine the fog factor. The depth of each pixel is used to compute the fog factor that is applied in the blending computations. You can apply pixel fog by using any of the fog formulas defined by members of the D3DFOGMODE enumerated type: D3DFOG_LINEAR, D3DFOG_EXP, or D3DFOG_EXP2. You implement the pixel fog formula in different ways, depending on the device. If the device doesn't support the complex fog formula you want to use, write your code to request a less complex formula or linear fog if necessary. Also remember that pixel fog doesn't support range-based fog calculations.

Eye-Relative Depth and z-Based Depth Pixel Fog

Eye-relative depth is basically the reciprocal of homogeneous w from a device space coordinate set. Most of the available hardware devices use eye-relative depth instead of z-based depth values for pixel fog because eye-relative depth doesn't create the artifacts that uneven distribution of z values in the z-buffer causes. The manufacturers of most 3D accelerators use the eye-relative approach because it provides the most realistic effects.

To determine whether a device supports eye-relative fog, check the D3DPRASTERCAPS_WFOG flag in the dwRasterCaps member of D3DPRIMCAPS with a call to the IDirect3DDevice7::GetCaps method. Although many hardware devices use the eye-relative approach, software devices (other than the reference rasterizer) always use z values to calculate pixel fog effects.

To ensure that Direct3D uses eye-relative depth instead of z-based depth when it's available, make sure that the projection matrix (set with the call to IDirect3DDevice7::SetTransform method) you provide produces z values in world space that are equivalent to w values in device space.

You need to remember that if the projection matrix includes a (3, 4) coefficient that is not 1, you need to scale all coefficients by the inverse of the (3, 4) coefficient to produce a compatible matrix. The following matrix shows a noncompliant projection matrix along with the same matrix scaled properly (compliant) so that eye-relative fog is enabled. (All variables contain nonzero values.) The equations in the matrix show how to scale the noncompliant matrix properly to make it compliant.

If you use an affine projection (the coefficients of the fourth column of the projection matrix are [0, 0, 0, 1]), Direct3D uses z-based depth values for the fog. As with vertex fog, if you use the linear fog formula, you need to set the starting and ending distances (defined in world space units) by using the D3DRENDERSTATE_FOGTABLESTART and D3DRENDERSTATE_FOGTABLEEND render states.

To use eye-relative fog, you need to ensure that perspective-correct texture mapping is enabled. You enable it by setting the D3DRENDERSTATE_TEXTUREPERSPECTIVE render state to TRUE (which is the default value in DirectX 7).

You set the pixel fog parameters by using the device render states. You control the formula you want the system to use by setting D3DRENDERSTATE_FOGTABLEMODE to the appropriate member from the D3DFOGMODE enumerated type.

Finally, you use the D3DRENDERSTATE_FOGTABLEDENSITY render state to control the fog density, which is applied when you use an exponential fog formula. The fog density is a weighting factor, ranging from 0.0 through 1.0 inclusive, that scales the distance value in the exponent.

You enable pixel fog just as you do vertex fog: by setting the D3DRENDERSTATE_FOGENABLE render state to TRUE. You control the fog color used for fog blending by using the D3DRENDERSTATE_FOGCOLOR render state controls.

Here's an example routine to set up pixel-based fog. As with the routine shown earlier, this routine is similar to the one shown in the Microsoft documentation. In the following "The Code So Far" section, I illustrate code I use for the RoadRage application that allows you to handle these tasks via a drop-down menu. Depending on your final application, using one or the other of these routines, or a combination of both, should allow you to handle any fog code tasks that come up.

 void DoPixelFog(DWORD dwColor, DWORD dwMode) {     HRESULT hr;     float fStart = 0.5f,    // For linear mode           fEnd   = 0.8f,           fDensity = 0.66;  // For exponential modes       // Enable fog blending.     hr = m_lpDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, TRUE);     if (FAILED(hr))         HandleError(hr);     // Set the fog color.     hr = m_lpDevice->SetRenderState(D3DRENDERSTATE_FOGCOLOR, dwColor);     if (FAILED(hr))         HandleError(hr);     // Set the fog parameters.     if(D3DFOG_LINEAR == dwMode)     {         hr = m_lpDevice->SetRenderState(D3DRENDERSTATE_FOGTABLEMODE,                                          dwMode);         if (FAILED(hr))             HandleError(hr);         Hr = m_lpDevice->SetRenderState(D3DRENDERSTATE_FOGSTART,                                          *(DWORD *)(&fStart));         if (FAILED(hr))             HandleError(hr);         hr = m_lpDevice->SetRenderState(D3DRENDERSTATE_FOGEND,                                            *(DWORD *)(&fEnd));         if (FAILED(hr))             HandleError(hr);     }     else     {         hr = m_lpDevice->SetRenderState(D3DRENDERSTATE_FOGTABLEMODE,                                          dwMode);         if (FAILED(hr))             HandleError(hr);         hr = m_lpDevice->SetRenderState(D3DRENDERSTATE_FOGDENSITY,                                          *(DWORD *)(&fDensity));         if (FAILED(hr))             HandleError(hr);     }   } 



Inside Direct3D
Inside Direct3D (Dv-Mps Inside)
ISBN: 0735606137
EAN: 2147483647
Year: 1999
Pages: 131

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net