Step 3 - Rendering the Scene

After scene geometry has been initialized, it is time to render the scene. In order to render an object with texture, the texture must be set as one of the current textures. The next step is to set the texture stage states values. Texture stage states enable you to define the behavior of how a texture or textures are to be rendered. For example, you could blend multiple textures together.

The Texture sample project starts by setting the texture to use. The following code fragment sets the texture that the Direct3D device will use to render with IDirect3DDevice9::SetTexture.

g_pd3dDevice->SetTexture( 0, g_pTexture );

The first parameter that IDirect3DDevice9::SetTexture accepts is a stage identifier to set the texture to. A device can have up to eight set textures, so the maximum value here is 7. The Texture sample project has only one texture and places it at stage 0. The second parameter is a pointer to a texture object. The Texture sample project uses the texture object that it created in its InitGeometry application-defined function.

The following code sample sets the texture stage state values by calling the IDirect3DDevice9::SetTextureStageState method.

    // Setup texture. Using textures introduces the texture stage states, which
    //   govern how textures get blended together (in the case of multiple
    //   textures) and lighting information. In this case, you are modulating
    //   (blending) your texture with the diffuse color of the vertices.
    g_pd3dDevice->SetTexture( 0, g_pTexture );
    g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_MODULATE );
    g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
    g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
    g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP,   D3DTOP_DISABLE );

#ifdef SHOW_HOW_TO_USE_TCI
    // Note: To use Direct3D texture coordinate generation, use the stage state
    // D3DTSS_TEXCOORDINDEX, as shown below. In this example, you are using
    // the position of the vertex in camera space to generate texture
    // coordinates. The tex coord index (TCI) parameters are passed into a
    // texture transform, which is a 4x4 matrix that transforms the x,y,z
    // TCI coordinates into tu, tv texture coordinates.

    // In this example, the texture matrix is set up to 
    // transform the texture from (-1,+1) position coordinates to (0,1) 
    // texture coordinate space:
    //    tu =  0.5*x + 0.5
    //    tv = -0.5*y + 0.5
    D3DXMATRIXA16 mat;
    mat._11 = 0.25f; mat._12 = 0.00f; mat._13 = 0.00f; mat._14 = 0.00f;
    mat._21 = 0.00f; mat._22 =-0.25f; mat._23 = 0.00f; mat._24 = 0.00f;
    mat._31 = 0.00f; mat._32 = 0.00f; mat._33 = 1.00f; mat._34 = 0.00f;
    mat._41 = 0.50f; mat._42 = 0.50f; mat._43 = 0.00f; mat._44 = 1.00f;

    g_pd3dDevice->SetTransform( D3DTS_TEXTURE0, &mat );
    g_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, 
	    	D3DTTFF_COUNT2 );
    g_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 
	    	D3DTSS_TCI_CAMERASPACEPOSITION );
#endif

The first parameter that IDirect3DDevice9::SetTextureStageState accepts is the stage index for the state variable to be set. This code sample changes the values for the texture at stage 0, so it puts a zero here. The next parameter is the texture state to set. For a list of all valid texture states and their meaning, see D3DTEXTURESTAGESTATETYPE. The next parameter is the value to which the texture state will be set. The value that you place here is based on the texture stage state value that you are modifying.

After setting up the desired values for each texture stage state, the cylinder can be rendered and texture will be added to the surface.

Another way to use texture coordinates is to automatically generate them. This is done by using a texture coordinate index (TCI). The TCI uses a texture matrix to transform the (x,y,z) TCI coordinates into (tu, tv) texture coordinates. In the Texture sample project, the position of the vertex in camera space is used to generate texture coordinates.

The first step is to create the matrix that will be used for the transformation, as demonstrated in the following code fragment.

D3DXMATRIX mat;
mat._11 = 0.25f; mat._12 = 0.00f; mat._13 = 0.00f; mat._14 = 0.00f;
mat._21 = 0.00f; mat._22 =-0.25f; mat._23 = 0.00f; mat._24 = 0.00f;
mat._31 = 0.00f; mat._32 = 0.00f; mat._33 = 1.00f; mat._34 = 0.00f;
mat._41 = 0.50f; mat._42 = 0.50f; mat._43 = 0.00f; mat._44 = 1.00f;

After the matrix is created, it must be set by calling IDirect3DDevice9::SetTransform, as shown in the following code fragment.

g_pd3dDevice->SetTransform( D3DTS_TEXTURE0, &mat );

The D3DTS_TEXTURE0 flag tells Direct3D to apply the transformation to the texture located at texture stage 0. The next step that this sample takes is to set more texture stage state values to get the desired effect. That is done in the following code fragment.

g_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, 
			D3DTTFF_COUNT2 );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 
			D3DTSS_TCI_CAMERASPACEPOSITION );

The texture coordinates are set up, and now the scene is ready to be rendered. Notice that the coordinates are automatically created for the cylinder. This particular setup gives the effect of the texture being laid over the rendering screen after the geometric shapes have been rendered.

For more information about textures, see Direct3D Textures.