DirectX SDK

Texture Coordinates for Cubic Environment Maps

[C++]

Texture coordinates that index a cubic-environment map aren't the simple u, v style coordinates used when standard textures are applied. In fact, cubic environment maps don't really use texture coordinates at all. In the place of a set of texture coordinates, cubic environment maps require a 3-D vector. You must take care to specify a proper vertex format. In addition to telling the system how many sets of texture coordinates your application uses, you must provide information about how many elements are in each set. Direct3D offers the D3DFVF_TEXCOORDSIZEn set of macros for this purpose. These macros accept a single parameter, identifying the index of the texture coordinate set for which the size is being described. In the case of a 3-D vector, you would include the bit pattern created by the D3DFVF_TEXCOORDSIZE3 macro. The following code shows how this macro is used.

// Create a flexible vertex format descriptor for a vertex that 
// contains a position, normal, and one set of 3-D texture 
// coordinates.
DWORD dwFVF = D3DFVF_XYZ | D3DFVF_NORMAL | 
              D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE3(0); 

In some cases, such as diffuse light mapping, you will use the camera-space vertex normal for the vector. In other cases, like specular environment mapping, you would use a reflection vector. (Because transformed vertex normals are widely understood, the information here concentrates on computing a reflection vector.)

Computing a reflection vector on your own requires understanding of the position of each vertex, and a vector from the viewpoint to that vertex. Direct3D can automatically compute the reflection vectors for your geometry. Using this feature saves memory (you don't need to include texture coordinates for the environment map); it reduces bandwidth; and in the case of a TnLHAL Device, it can be significantly faster than the computations your application could make on its own. To take advantage of this feature, in the texture stage that contains the cubic-environment map, simply set the D3DTSS_TEXCOORDINDEX texture stage state to a combination of the D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR flag and the index of a texture coordinate set. (In some situations, like diffuse light mapping, you might use the D3DTSS_TCI_CAMERASPACENORMAL flag, which causes the system to use the transformed, camera-space, vertex normal as the addressing vector for the texture.) The index is only used by the system to determine the wrapping mode for the texture.

The following code shows how this value is used.

// The pd3dDevice variable is a valid pointer to an 
// IDirect3DDevice7 interface.

// Automatically generate texture coordinates for stage 2. T
// This assumes that stage 2 is assigned a cube map.
// (Use the wrap mode from the texture coord set at index 1.)
pd3dDevice->SetTextureStageState( 2, D3DTSS_TEXCOORDINDEX, 
                                  D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR | 1); 

When you enable automatic texture coordinate generation, the system uses one of two formulas to compute the reflection vector for each vertex. When the D3DRENDERSTATE_LOCALVIEWER render state is set to TRUE, the formula used is the following:

In the preceding formula, R is the reflection vector being computed, E is the normalized position-to-eye vector, and N is the camera-space vertex normal.

When the D3DRENDERSTATE_LOCALVIEWER render state is set to FALSE, the system uses the following formula.

The R and N elements in this formula are identical to the previous formula. The Nz element is the world-space z of the vertex normal, and I is the vector (0,0,1) of an infinitely distant viewpoint. The system uses the reflection vector from either formula to select and address the appropriate face of the cube map.

Note  In most cases, applications should enable automatic normalization of vertex normals. To do this, set D3DRENDERSTATE_NORMALIZENORMALS to TRUE. If you do not enable this render state, the appearance of the environment map will be drastically different than you might expect.

[Visual Basic]

Texture coordinates that index a cubic-environment map aren't the simple u, v style coordinates used when standard textures are applied. In fact, cubic environment maps don't really use texture coordinates at all. In the place of a set of texture coordinates, cubic environment maps require a 3-D vector. You must take care to specify a proper vertex format. In addition to telling the system how many sets of texture coordinates your application uses, you must provide information about how many elements are in each set. Direct3D offers the D3DFVF_TEXCOORDSIZEn set of helper functions in the Math.bas source file for this purpose. (The Math.bas file ships with this SDK.) These accept a single parameter, identifying the index of the texture coordinate set for which the size is being described. In the case of a 3-D vector, you would include the bit pattern created by the D3DFVF_TEXCOORDSIZE3 helper-function. The following code shows how this function is used.

' Create a flexible vertex format descriptor for a vertex that 
' contains a position, normal, and one set of 3-D texture 
' coordinates.
Dim lFVF As Long
lFVF = D3DFVF_XYZ Or D3DFVF_NORMAL Or 
       D3DFVF_TEX1 Or D3DFVF_TEXCOORDSIZE3(0) 

In some cases, such as diffuse light mapping, you will use the camera-space vertex normal for the vector. In other cases, like specular environment mapping, you would use a reflection vector. (Because transformed vertex normals are widely understood, the information here concentrates on computing a reflection vector.)

Computing a reflection vector on your own requires understanding of the position of each vertex, and a vector from the viewpoint to that vertex. Direct3D can automatically compute the reflection vectors for your geometry. Using this feature saves memory (you don't need to include texture coordinates for the environment map); it reduces bandwidth; and in the case of a TnLHAL Device, it can be significantly faster than the computations your application could make on its own. To take advantage of this feature, in the texture stage that contains the cubic-environment map, simply set the D3DTSS_TEXCOORDINDEX texture stage state to a combination of the D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR flag and the index of a texture coordinate set. (In some situations, like diffuse light mapping, you might use the D3DTSS_TCI_CAMERASPACENORMAL flag, which causes the system to use the transformed, camera-space, vertex normal as the addressing vector for the texture.) The index is only used by the system to determine the wrapping mode for the texture.

The following code shows how this value is used.

' The pd3dDevice variable is a valid reference to a 
' Direct3DDevice7 object.

' Automatically generate texture coordinates for stage 2. T
' This assumes that stage 2 is assigned a cube map.
' (Use the wrap mode from the texture coord set at index 1.)
Call d3dDevice.SetTextureStageState(2, D3DTSS_TEXCOORDINDEX, 
                                    D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR Or 1)

When you enable automatic texture coordinate generation, the system uses one of two formulas to compute the reflection vector for each vertex. When the D3DRENDERSTATE_LOCALVIEWER render state is set to True, the formula used is the following:

In the preceding formula, R is the reflection vector being computed, E is the normalized position-to-eye vector, and N is the camera-space vertex normal.

When the D3DRENDERSTATE_LOCALVIEWER render state is set to False, the system uses the following formula.

The R and N elements in this formula are identical to the previous formula. The Nz element is the world-space z of the vertex normal, and I is the vector (0,0,1) of an infinitely distant viewpoint. The system uses the reflection vector from either formula to select and address the appropriate face of the cube map.

Note  In most cases, applications should enable automatic normalization of vertex normals. To do this, set D3DRENDERSTATE_NORMALIZENORMALS to True. If you do not enable this render state, the appearance of the environment map will be drastically different than you might expect.