Setting Up Fog

[Previous] [Next]

As with most aspects of Direct3D Immediate Mode, you control the fog parameters using device render states. You can set the color used for fog blending by using the D3DRENDERSTATE_FOGCOLOR device render state as shown here:

 // Set the fog color. m_pd3dDevice->SetRenderState(D3DRENDERSTATE_FOGCOLOR,                              RGB_MAKE(0, 0, 80)); 

In the project for this chapter on the companion CD, we add the code to set the fog color to blue using this command to enable proper blending with the scene's background.

You use the D3DRENDERSTATE_FOGTABLEMODE render state to specify the fog mode that will be used when you choose pixel fog. If you choose to use vertex fog, the D3DRENDERSTATE_FOGVERTEXMODE render state specifies the fog mode that will be used.

With vertex fog, fog calculations are applied at each vertex in a polygon and the results are then interpolated across the face of the polygon during rasterization. To enable vertex fog, call the SetRenderState method with D3DRENDERSTATE_FOGENABLE as the first parameter and TRUE as the second. Vertex fog supports only the linear fog formula; to specify that formula, call the SetRenderState method with D3DRENDERSTATE_FOGVERTEXMODE and the D3DFOG_LINEAR member of the D3DFOGMODE enumerated type. Additionally, you should set the color of the fog based on the color of your rendered 3D world. Here are the necessary calls:

 m_lpDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, TRUE); m_lpDevice->SetRenderState(D3DRENDERSTATE_FOGVERTEXMODE,                            D3DFOG_LINEAR); m_lpDevice->SetRenderState(D3DRENDERSTATE_FOGCOLOR, dwColor); 

The lighting and transformation engines compute vertex fog effects, and the fog is applied during the lighting stage. You also need to set the starting and ending distances (defined in world space) for linear fog by using the D3DRENDERSTATE_FOGSTART and D3DRENDERSTATE_FOGEND lighting states. These two values define the distances at which fog begins and ends in a scene.

The code to set all these states is shown below. This code and the DoPixelFog routine we'll cover in the next section are basically the same as the routines of the same name used in many of the Microsoft demo programs contained on this book's companion CD. However, these routines check for any errors and handle them appropriately. Microsoft recommends that you provide any floating-point values required by calls to the IDirect3DDevice7::SetRenderState methods without data transitions by casting the address of the floating-point variables as DWORD pointers and then dereferencing them. The calls in this routine illustrate how to use this approach.

 void DoVertexFog(DWORD dwColor, DWORD dwMode,                  BOOL fUseRange, FLOAT fDensity) {     HRESULT hr;     float fStart = 0.5f,    // linear fog distances           fEnd   = 0.8f;       // 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_FOGVERTEXMODE,                                          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_FOGVERTEXMODE,                                         dwMode);         if (FAILED(hr))             HandleError(hr);         hr = m_lpDevice->SetRenderState(D3DRENDERSTATE_FOGDENSITY,                                          *(DWORD *)(&fDensity));         if (FAILED(hr))             HandleError(hr);     }     //     // Enable range-based fog if desired (supported only for vertex fog).     // fUseRange is set to a nonzero value only if the driver exposes     // the D3DPRASTERCAPS_FOGRANGE capability.     //      if(fUseRange)     {         hr = m_lpDevice->SetRenderState(D3DRENDERSTATE_RANGEFOGENABLE,                                         TRUE);         if (FAILED(hr))                 HandleError(hr);     } } 

Range-Based Fog

Fog can sometimes cause objects to blend with the fog color in odd ways. One situation in which you'd see strange effects is when one of the objects is far enough away to be affected by fog and a second object is close enough not to have been affected yet. This situation is shown in Figure 9-2.

click to view at full size.

Figure 9-2 An object out of the fog area

By rotating the original view shown in Figure 9-2—but without moving the viewpoint—you can change the fog effects even if the objects are stationary. This rotation causes an object that wasn't obscured by fog to become obscured, creating an unrealistic flicker effect as the object becomes brighter or dimmer in relation to the overall scene. Figure 9-3 illustrates what happens to the objects in Figure 92 as the view is rotated.

click to view at full size.

Figure 9-3 Rotating the view so that an object is in the fog area

To address this undesirable effect, and other related problems, Direct3D provides range-based fog. With range-based fog, the distance from the viewpoint to the object's vertices is used to compute the fog. Fog increases as the distance between the viewpoint and each vertex increases, as opposed to the unrealistic-flicker-effect scenario described earlier, in which the depth of the vertex within the scene is used to compute the fog effects. This approach keeps rotational artifacts from occurring. Figure 9-4 shows how range-based fog keeps objects within the fog range. By using the fog's starting and ending ranges in conjunction with the current viewpoint, Direct3D correctly computes fog effects as the view changes.

Figure 9-4 Range-based fog

If the device on the target system supports range-based fog, the D3DPRASTERCAPS_FOGRANGE capability flag will be set in the dwRasterCaps member of the D3DPRIMCAPS structure when you call the IDirect3DDevice7::GetCaps method. If it is available on the target system, range-based fog can be enabled by setting the D3DRENDERSTATE_RANGEFOGENABLE render state to TRUE. Here's an example of the call required:

 m_lpDevice->SetRenderState(D3DRENDERSTATE_RANGEFOGENABLE, TRUE); 

No one yet manufactures hardware that supports per-pixel range-based fog. Because of this, Direct3D employs range-based fog only when you use vertex fog.



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