Setting Render States

[Previous] [Next]

A Direct3D device has dozens of settings that you can change to affect how primitives are rendered. These settings are called render states. You can use the IDirect3DDevice7::SetRenderState method to change a render state. This method takes as parameters a member of the D3DRENDERSTATETYPE enumerated type and a new value for the specified render state. The meaning of the second parameter is dependent on the value specified for dwRenderStateType.

Here's the function declaration for this method:

 HRESULT IDirect3DDevice7::SetRenderState(     D3DRENDERSTATETYPE dwRenderStateType,     DWORD dwRenderState ); 

ParameterDescription
dwRenderStateTypeThe device state variable that this function changes. This parameter can be any member of the D3DRENDERSTATETYPE enumerated type.
dwRenderStateThe new value for the Direct3DDevice render state. This parameter is dependent on the dwRenderStateType parameter.

All the Direct3D render states have default values, so you don't have to set every single render state before you start rendering primitives. The render states that you choose to change will depend on the needs of your program. In some cases, you will set a render state once upon creation of the Direct3D device. In other cases, you will change the render state when the user changes a program setting or when rendering a particular object. As an example, the following code segment uses SetRenderState to set the render state for the cull, shade, and fill modes, and the ambient light level of a simple scene.

 HRESULT CMyD3DApplication::Render() {     // Clear the viewport.     lpDev7->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,                    0x000000ff, 1.0f, 0L );     DWORD dwCullMode  = m_bCull ? D3DCULL_CCW : D3DCULL_NONE;     DWORD dwShadeMode = m_bFlat ? D3DSHADE_FLAT : D3DSHADE_GOURAUD;     DWORD dwFillMode  = m_bWire ? D3DFILL_WIREFRAME : D3DFILL_SOLID;     lpDev7->SetRenderState( D3DRENDERSTATE_CULLMODE,  dwCullMode );     lpDev7->SetRenderState( D3DRENDERSTATE_SHADEMODE, dwShadeMode );     lpDev7->SetRenderState( D3DRENDERSTATE_FILLMODE,  dwFillMode );     lpDev7->SetRenderState( D3DRENDERSTATE_AMBIENT,                              RGBA_MAKE(128,128,128,128) );     // Begin the scene.      if( SUCCEEDED( m_pd3dDevice->BeginScene() ) )     {         if( m_pFileObject )             m_pFileObject->Render( m_pd3dDevice );         // End the scene.         m_pd3dDevice->EndScene();     }     return S_OK; } 

When rendering primitives, keep in mind that 3D acceleration hardware can quickly process a series of primitives that are all the same type, but it can be slowed down by changing the type of rendering more than is necessary. Switching to a different texture map can slow down rendering, as can changing the render state. To maximize performance, try to render all primitives that share a texture (and ideally, the same render states) at once, then change texture (and render state if necessary), then render more primitives, and so on.

The following sections describe the render states that you'll most likely want to use. In subsequent chapters, we'll be covering several of these states in detail, but for now, I'll provide a quick overview of the available states so that you can begin to see how these commands work together.

Alpha Blending States

Alpha blending (which allows the rendering of semitransparent objects) can be activated through the setting of a few render states. You can use the D3DRENDERSTATE_ALPHABLENDENABLE render state to enable alpha transparency blending on devices that support it. The D3DRENDERSTATE_SRCBLEND and D3DRENDERSTATE_DESTBLEND render states define the type of alpha blending that is performed. An example is shown here:

 // // Enable alpha blending. // lpDev7->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE,                              TRUE); // // Set the source blend state. // lpDev7->SetRenderState(D3DRENDERSTATE_SRCBLEND,                              D3DBLEND_SRCCOLOR); //  // Set the destination blend state. // lpDev7->SetRenderState(D3DRENDERSTATE_DESTBLEND,                              D3DBLEND_INVSRCCOLOR); 

After setting these states, you can render primitives that contain alpha in their vertex color, material, or texture map. Where the alpha value is 1.0, the object will be opaque. Where the alpha value is 0.0, the object will be transparent. Values between 0.0 and 1.0 will cause the object to be semitransparent.

Alpha Testing State

Alpha testing controls whether pixels are written to the render-target surface—that is, it verifies whether the pixels are accepted or rejected. The D3DRENDERSTATE_ALPHAREF render state lets you use alpha testing to determine whether a color about to be rendered for a pixel is more opaque than the one already at that pixel by using the D3DPCMPCAPS_GREATEREQUAL render state. If the color about to be rendered is more opaque, the pixel is written. If the color isn't more opaque, that pixel is skipped. This approach saves the time required to blend the colors.

The following command sets the current Direct3D device so that it tests each pixel according to an alpha test function:

 // // Set the alpha testing state. // if (pd3dDeviceDesc.dpcTriCaps.dwAlphaCmpCaps &      D3DPCMPCAPS_GREATEREQUAL) {     lpDev7->SetRenderState( D3DRENDERSTATE_ALPHAREF,                              (DWORD)0x00000001);     lpDev7->SetRenderState( D3DRENDERSTATE_ALPHATESTENABLE,                              TRUE );      lpDev7->SetRenderState( D3DRENDERSTATE_ALPHAFUNC,                              D3DCMP_GREATEREQUAL); } 

You can set the alpha test function with the D3DRENDERSTATE_ALPHAFUNC enumerated value. You can set a reference alpha value for all pixels to be compared against by using the D3DRENDERSTATE_ALPHAREF render state.

The code to perform alpha testing and determine whether the available device supports alpha testing appears in detail in Chapter 10.

Ambient Lighting State

As mentioned in Chapter 5, ambient light is the light that surrounds the object and emanates from all directions. This lighting is used as the background lighting for the RoadRage application. You control the color of the ambient lighting by using the IDirect3DDevice7::SetRenderState method and passing it the enumerated value D3DLIGHTSTATE_AMBIENT as the first parameter. The second parameter is a color in RGBA format. The following code sets the ambient light color:

 // // Set the ambient light. // D3DCOLOR d3dclrAmbientLightColor = D3DRGBA(1.0f,1.0f,1.0f,1.0f); lpDev7->SetRenderState(D3DRENDERSTATE_AMBIENT,                         d3dclrAmbientLightColor); 

Antialiasing State

Antialiasing makes lines and edges look as smooth as possible on the screen. Direct3D provides a render state for full-scene antialiasing if the Direct3D device supports it but defaults to not performing antialiasing (D3DRENDERSTATE_ANTIALIAS set to D3DANTIALIAS_NONE, a member of D3DANTIALIASMODE, which disables full-screen antialiasing). The following command enables sort-independent antialiasing, which means that antialiasing isn't to depend on the order in which the polygons are rendered:

 // // Set up antialiasing. // lpDev7->SetRenderState(D3DRENDERSTATE_ANTIALIAS,      D3DANTIALIAS_SORTINDEPENDENT); 

Clipping State

Primitives being rendered partially outside the viewport can be clipped. You can disable clipping (it is enabled by default) by setting the D3DRENDERSTATE_CLIPPING render state to FALSE, as follows:

 // // Set the clipping state. // lpDev7->SetRenderState(D3DRENDERSTATE_CLIPPING, FALSE); 

The primitive clipping render state is different than those used for vertices in a vertex buffer.

Color Keying State

You can set a color key to treat the key color as transparent. Once set, whenever a texture is applied to one of the primitives, all the texels that match the key color won't be rendered on the primitive (making the primitive effectively transparent at that point). You can set the color key by using the IDirectDrawSurface7::SetColorKey method for the surface that will be using the color key and then toggle it on and off with a call, as follows:

 // // Turn on color keying. // lpDev7->SetRenderState(D3DRENDERSTATE_COLORKEYENABLE, FALSE); 

Setting the second parameter to TRUE enables color keying; setting it to FALSE disables color keying.

Culling State

When you set up a triangle that you want to see both sides of, you usually should make sure that you create two triangles instead of one—one that represents the front of the triangle and one that represents the back. You need to do this because Direct3D culls any primitives that are facing away from the camera during rendering. By rendering both the front and back triangles, the triangle is visible from both sides because you've rendered two triangles instead of just one.

Direct3D defaults to culling backfaces with counterclockwise vertices. In other words, Direct3D assumes that you specify the vertices in counterclockwise order when facing the triangle from the side that you want to be visible. You can change the culling mode of a Direct3D device by calling SetRenderState with render-state type D3DRENDERSTATE_CULLMODE and a constant from the D3DCULL enumerated type. Although you'll rarely need to change the culling mode, you might need to do so in either of these two cases:

  • You need to import 3D content that specifies triangles in the counterclockwise direction.
  • You're attempting to find out why you can't see an object, so you use D3DCULL_NONE to keep Direct3D from culling any objects.

This next code segment shows how to set the culling mode to cull backfaces with clockwise vertices:

 //  // Set the culling mode. // lpD3DDevice7->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_CW); 

You can use the D3DCULL enumerated type just mentioned to define the supported cull modes that specify how backfaces are culled when rendering 3D objects. Here's the definition for this type:

 typedef enum _D3DCULL {      D3DCULL_NONE = 1,      D3DCULL_CW   = 2,      D3DCULL_CCW  = 3,      D3DCULL_FORCE_DWORD   = 0x7fffffff,  } D3DCULL; 

These members have the following uses:

  • D3DCULL_NONE Backfaces aren't culled.
  • D3DCULL_CW Backfaces with clockwise vertices are culled.
  • D3DCULL_CCW Backfaces with counterclockwise vertices are culled.
  • D3DCULL_FORCE_DWORD Forces this enumerated type to be 32 bits.

Depth-Buffering State

Depth buffering removes hidden lines and surfaces. By default, Direct3D doesn't perform depth buffering. You can set the depth-buffering state by using the D3DRENDERSTATE_ZENABLE render state and passing it one of the members of the D3DZBUFFERTYPE enumerated type. The following code sets the depth-buffer state to enable z-buffering:

 //  // Enable z-buffering. // lpDev7->SetRenderState(D3DRENDERSTATE_ZENABLE, D3DZB_TRUE); 

Fill State

By default, Direct3D fills in the contents of the triangles that you specify. But it can also be configured to draw just the "wireframe" outline of the triangle or render just a single pixel at each vertex of the triangle. You can select the method for filling primitives by using D3DRENDERSTATE_FILLMODE and specifying a value from the D3DFILLMODE enumerated type. This enumerated type holds the constants that define the possible fill modes and is defined as follows:

 typedef enum _D3DFILLMODE {      D3DFILL_POINT     = 1,      D3DFILL_WIREFRAME = 2,      D3DFILL_SOLID     = 3      D3DFILL_FORCE_DWORD   = 0x7fffffff,  } D3DFILLMODE; 

These members cause Direct3D to fill primitives as follows:

  • D3DFILL_POINT Causes Direct3D to draw a 1-pixel point at each specified vertex.
  • D3DFILL_WIREFRAME Causes Direct3D to draw lines between specified vertices. This mode doesn't work for clipped primitives when you're using the DrawPrimitive methods.
  • D3DFILL_SOLID Causes Direct3D to fill the interiors of the specified triangles.
  • D3DFILL_FORCE_DWORD Forces this enumerated type to be 32 bits.

Fog State

You can use fog effects to simulate fog or to decrease the clarity of a scene with distance. The latter technique causes objects to become hazy as they become more distant from the viewer, as happens in real life. To enable fog, you can use the following code:

 // // Turn on fog. // FLOAT fFogStart =  1.0f; FLOAT fFogEnd   = 50.0f; lpDev7->SetRenderState( D3DRENDERSTATE_FOGENABLE,    TRUE ); lpDev7->SetRenderState( D3DRENDERSTATE_FOGCOLOR,     WATER_COLOR ); lpDev7->SetRenderState( D3DRENDERSTATE_FOGTABLEMODE, D3DFOG_NONE ); lpDev7->SetRenderState( D3DRENDERSTATE_FOGVERTEXMODE, D3DFOG_LINEAR); lpDev7->SetRenderState( D3DRENDERSTATE_FOGSTART,                          *((DWORD *)(&fFogStart))); lpDev7->SetRenderState( D3DRENDERSTATE_FOGEND,                          *((DWORD *)(&fFogEnd)) ); 

Chapter 9 includes more detail about the fog types supplied by Direct3D. In that chapter you'll also find out how to add support for the various fog types.

Lighting State

You can enable or disable lighting calculations. (They are enabled by default.) Vertices containing a vertex normal are the only ones that will be properly lit. Any others will use a dot product of 0 in all lighting computations, so they will end up receiving no lighting.

 // // Turn off lighting. // lpDev7->SetRenderState(D3DRENDERSTATE_LIGHTING, FALSE); 

Outline State

Direct3D devices default to using a solid outline for primitives. You can easily change the outline pattern by using the D3DLINEPATTERN structure, as this code segment shows:

 //  // Set the outline pattern. // // Line pattern of 1100110011001100 (0xCCCC) produces a dashed line. DWORD linePattern= 0xCCCC; lpD3DDevice7->SetRenderState(D3DRENDERSTATE_LINEPATTERN,                               linePattern); 

Per-Vertex Color States

The flexible vertex format allows vertices to contain both vertex color and vertex normal information (though the D3DVERTEX, D3DLVERTEX, and D3DTLVERTEX vertex types can't contain both color and normal information). The color and normal are used for lighting computation. If you choose to disable using vertex color lighting information, you make the following call:

 lpDev7->SetRenderState(D3DRENDERSTATE_COLORVERTEX, FALSE);  

You can set the source from which the system gets the color information for a vertex (when per-vertex color is enabled) with the following render states:

  • D3DRENDERSTATE_DIFFUSEMATERIALSOURCE
  • D3DRENDERSTATE_SPECULARMATERIALSOURCE
  • D3DRENDERSTATE_AMBIENTMATERIALSOURCE
  • D3DRENDERSTATE_EMISSIVEMATERIALSOURCE

These render states control the color sources for the diffuse, specular, ambient, and emissive color component sources. By setting these states to members of the D3DMATERIALCOLORSOURCE enumerated type, constants are set to request the use of the current material, diffuse color, or specular color as the source for the specified color component.

Shading State

Although Direct3D defaults to Gouraud shading, you can use flat shading. You can set the shading state to flat-shading mode as follows:

 // // Set the shading state. // lpDev7->SetRenderState(D3DRENDERSTATE_SHADEMODE,  D3DSHADE_FLAT); 

Stencil Buffering States

You can use the stencil buffer to decide whether a pixel is written to the rendering target surface. You can enable stenciling by using the following call:

 //  // Set the stencil buffer state. // lpDev7->SetRenderState(D3DRENDERSTATE_STENCILENABLE, TRUE); 

Once this state is set, you can set the comparison function that performs the stencil test as follows, passing a member of the D3DCMPFUNC enumerated type as the second value:

 //  // Set the stencil test comparison test to less than or equal. // lpDev7->SetRenderState(D3DRENDERSTATE_STENCILFUNC,                         D3DCMP_LESSEQUAL); 

You also need to set the stencil reference value, which is the stencil buffer that the stencil function uses for its test, as follows:

 // // Set the stencil reference value. // lpDev7->SetRenderState(D3DRENDERSTATE_STENCILREF, newRef); 

Before performing the stencil test for a pixel, Direct3D does a bitwise AND of the stencil reference value and a stencil mask value and compares the result against the contents of the stencil buffer using the stencil comparison function. You can set the stencil mask with the following command:

 //  // Set the stencil mask. // lpDev7->SetRenderState(D3DRENDERSTATE_STENCILMASK,                         newStencilMask); 

You can define what occurs when the stencil test fails with this command:

 //  // Define what happens when the stencil test fails. // lpDev7->SetRenderState(D3DRENDERSTATE_STENCILFAIL,                         D3DSTENCILOP_REPLACE); 

The second argument is a value from the D3DSTENCILOP enumerated type.

You can define what occurs when the stencil test passes but the depth-buffer test fails with this command:

 //  // Define what happens when the stencil test  // passes but the depth-buffer text fails. // lpDev7->SetRenderState(D3DRENDERSTATE_STENCILZFAIL,                         D3DSTENCILOP_REPLACE); 

The second argument is passed as a value from the D3DSTENCILOP enumerated type.

Finally, you can define what occurs when both the stencil test and the depth-buffer test pass with this command:

 //  // Define what happens when both the stencil and depth-buffer  // tests pass. // lpDev7->SetRenderState(D3DRENDERSTATE_STENCILPASS,                         D3DSTENCILOP_REPLACE); 

The second argument is passed as a value from the D3DSTENCILOP enumerated type.

Texture Perspective State

You can apply perspective correction to textures to make them fit properly onto primitives that diminish in size as they get farther away from the viewer. You must enable perspective correction to use w-based fog and w-buffers.

The default value is TRUE, which enables perspective-correct texture mapping. Also, many of today's adaptors will apply perspective correction automatically.

The D3DRENDERSTATE_TEXTUREPERSPECTIVE render state is used to do this as follows:

 // Enable texture perspective. lpD3DDevice7->SetRenderState(D3DRENDERSTATE_TEXTUREPERSPECTIVE,                               TRUE); 

Texture Wrapping State

The D3DRENDERSTATE_WRAP0 through D3DRENDERSTATE_WRAP7 render states are used to enable and disable u-wrapping and v-wrapping for various textures in the device's multitexture cascade.

The states allow you to enable wrapping in first, second, third, and fourth directions of the texture. You can set these render states to a combination of the D3DWRAPCOORD_0, D3DWRAPCOORD_1, D3DWRAPCOORD_2, and D3DWRAPCOORD_3 flags. If you specify a value of 0, wrapping will be disabled completely, but texture wrapping is disabled in all directions for all texture stages by default anyway.

The following code segment illustrates the calls to set the texture-wrapping state:

 // // Set wrap flags for both coordinates in first set of texcoords: // m_pd3dDevice->SetRenderState( D3DRENDERSTATE_WRAP0,  D3DWRAPCOORD_0|D3DWRAPCOORD_1 ); 

Vertex Color Lighting State

The flexible vertex format allows vertices to contain both vertex color and vertex normal information. Direct3D defaults to using this information when it calculates lighting.

 //  // Disable vertex lighting. // lpDev7->SetRenderState(D3DRENDERSTATE_COLORVERTEX, FALSE); 

If you want your application to disable the use of vertex color lighting information, call the IDirect3DDevice7::SetRenderState method and pass D3DRENDERSTATE_COLORVERTEX as the first parameter and set the second parameter to FALSE. This setting causes the output alpha value to be equal to the alpha component of diffuse material, clamped to a range from 0 through 255. If you set the second parameter to TRUE and specify a diffuse vertex color, the output alpha value will be equal to the diffuse alpha value for the vertex.

z-Biasing State

With z-biasing, Direct3D allows you to display one surface in front of another even if the surfaces have the same depth values. You can use this technique to produce effects such as shadows. By providing a z-bias to a shadow, you can make the shadow display properly (appear on the wall) even though the shadow is at the same depth as the wall. The dwRenderState parameter, set to 12 in the following code segment, can be set to a value from 0 through 16:

 //  // Use z-biasing. // lpDev7->SetRenderState(D3DRENDERSTATE_ZBIAS, 12); 

Setting a high z-bias makes it more likely that your polygons will be visible when they're displayed with other polygons that are coplanar.



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