Environment mapping is a relatively simple technique that tries to simulate the look of reflective surfaces such as water or metals. Instead of computing the true reflection, which is a costly process, it uses a texture map and some texture coordinate trickery to create a quite convincing reflective effect. Notice, however, that environment mapping does not simulate true reflections. It is just a clever mathematical trick that fools the eye almost completely.
An environment map is just a regular texture map that we use to encode the reflections for a specific object. For example, if we want to display a teapot in the middle of a large room, the environment map encodes the room information, and then we use some techniques to assign mapping coordinates over that texture map. The map is usually projected either in spherical coordinates or by using a cube. Spherical coordinates are easier to create, but the result suffers some distortion at the poles. Cube mapping, on the other hand, suffers no distortion, is supported by new hardware, and opens the door to computing true reflections. All we need to do is generate a dynamic cube map whose six faces encode the reflection information for an object.
As far as implementation goes, environment mapping needs texture coordinates to be computed per frame. If the teapot rotates, we will see different reflections on its surface. Recall from the previous chapter that reflections are largely view dependent, and thus environment mapping is always dynamic. Now, these mapping coordinates are not that hard to compute. For a spherical map, all we have to do is get the per-vertex normal, convert it from XYZ to polar coordinates, and use these coordinates to access the environment map. Luckily, both OpenGL and DirectX support automatic texturing coordinate generation, so all we have to do is ask our API of choice for automatic generation on spheres, planes, or cubes, and it will handle it internally, much faster than a software implementation. In OpenGL, automatic texture generation is controlled by the glTexGen call. For a sphere map, the call must be
glTexGen(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glTexGen(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glTexGen(GL_Q, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
Under DirectX, the same can be achieved by using
d3dDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACENORMAL );
which sets texture coordinates to be computed from the surface's normal, thus yielding spherical coordinates.
Using environment mapping in only one texture stage and combining it (using texture combiners) with other stages yields extremely realistic results. Metallic surfaces that combine reflectivity with rust, or bump-mapped, reflective water are both possible using these techniques together.