Multitexturing (Texture Mapping) (OpenGL Programming)

During standard texturing, a single texture image is applied once to a polygon. Multitexturing allows several textures to be applied, one by one in a pipeline of texture operations, to the same polygon. There is a series of texture units, where each texture unit performs a single texturing operation and successively passes its result onto the next texture unit, until all defined units are completed. Figure 9-14 shows how a fragment might undergo four texturing operations—one for each of four texture units.

Multitexturing enables advanced rendering techniques, such as lighting effects, decals, compositing, and detail textures.

Multitexture Processing Pipeline

Figure 9-14 Multitexture Processing Pipeline

Steps in Multitexturing

To write code that uses multitexturing, perform the following steps:

Note: In feedback mode, multitexturing is undefined beyond the first texture unit.

1.For each texturing unit, establish the texturing state, including texture image, filter, environment, coordinate generation, and matrix. Use glActiveTexture() to change the current texture unit. This is discussed further in the next subsection, "Establishing Texture Units." You may also call glGetIntegerv(GL_MAX_TEXTURE_UNITS,…) to see how many texturing units are available on your implementation. In a worst-case scenario, there are at least two texture units.


2.During vertex specification, use glMultiTexCoord*() to specify more than one texture coordinate per vertex. A different texture coordinate may be used for each texturing unit. Each texture coordinate will be used during a different texturing pass. Automatic texture-coordinate generation and specification of texture coordinates in vertex arrays are special cases of this situation. The special cases are described in "Other Methods of Texture-Coordinate Specification" on page 443.

Establishing Texture Units

Multitexturing introduces multiple texture units, which are additional texture application passes. Each texture unit has identical capabilities and houses its own texturing state, including the following:

•    Texture image

•    Filtering parameters

•    Environment application

•    Texture matrix stack

•    Automatic texture-coordinate generation

•    Vertex-array specification (if needed)

Each texture unit combines the previous fragment color with its texture image, according to its texture state. The resulting fragment color is passed onto the next texture unit, if it is active.

To assign texture information to each texture unit, the routine glActiveTexture() selects the current texture unit to be modified. After that, calls to glTexImage*(), glTexParameter*(), glTexEnv*(), glTexGen*(), and glBindTexture() affect only the current texture unit. Queries of these texture states also apply to the current texture unit, as well as queries of the current texture coordinates and current raster texture coordinates.

void glActiveTexturefGLenum texUnit);

Selects the texture unit that is currently modified by texturing routines. texUnit is a symbolic constant of the form GL JT.XTURK/, where i is in the range from 0 to k – 1, and k is the maximum number of texture units.

If you use texture objects, you can bind a texture to the current texture unit. The current texture unit has the values of the texture state contained within the texture object (including the texture image).

The following code fragment, Example 9-10, has two distinct parts. In the first part, two ordinary texture objects are created (assume the arrays texelsO and texelsl define texture images). In the second part, the two texture objects are used to set up two texture units.

Example 9-10 Initializing Texture Units for Multitexturing: multitex.c

Initializing Texture Units for Multitexturing: multitex.c

When a textured polygon is now rendered, it is rendered with two textunng units. In the first unit, the texelsO texture image is applied with nearest texel filtering, repeat wrapping, replacement texture environment, and a texture matrix that rotates the texture image. After the first unit is completed, the newly textured polygon is sent onto the second texture unit (GL_TEXTURE1), where it is processed with the texelsl texture image with linear filtering, edge clamping, modulation texture environment, and the default identity texture matrix.

Note: Operations to a texture attribute group (using glPushAttrib(),glPushClientAttrib(), glPopAttrib(), or glPopClientAttrib()) save or restore the texture state of all texture units (except for the texture matrix stack).

Specifying Vertices and Their Texture Coordinates

With multitexturing, it isn’t enough to have one set of texture coordinates per vertex. You need to have one set for each texture unit for each vertex. Instead of using glTexCoord*(), you must use glMultiTexCoord*(), which specifies the texture unit, as well as the texture coordinates.

void gIMultiTexCoord|1234}{sifd}(GLenum texUnit, TYPE coords); void gl\lultiTexCoord[1234} jsifdlv(GLenum texUnit, TYPE *coords);

Sets the texture-coordinate data (s, t, r, q) in coords for use with the texture unit texUnit. The enumerated values for texUnit are the same as for glActiveTextureQ.

In Example 9-11, a triangle is given the two sets of texture coordinates necessary for multitexturing with two active texture units.

Example 9-11 Specifying Vertices for Multitexturing

Specifying Vertices for Multitexturing

Note: If you are multitexturing and you use glTexCoord*(), you are setting the texture coordinates for the first texture unit. In other words, using glTexCoord*() is equivalent to using glMultiTexCoord*(GL_ TEXTUREO,…).

In the rare case that you are multitexturing a bitmap or image rectangle, you need to associate several texture coordinates with each raster position. Therefore, you must call glMultiTexCoord*() several times, once for each active texture unit, for each glRasterPos*() or glWindowPos*() call. (Since there is only one current raster position for the entire bitmap or image rectangle, there is only one corresponding texture coordinate per unit, so the aesthetic possibilities are extremely limited.)

Other Methods of Texture-Coordinate Specification

Explicitly calling glMultiTexCoord*() is only one of three ways to specify texture coordinates when multitexturing. The other two ways are to use automatic texture-coordinate generation (with glTexGen*()) or vertex arrays (with glTexCoordPointer()).

If you are multitexturing and using automatic texture-coordinate generation, then glActiveTexture() directs which texture unit is affected by the following automatic texture-coordinate generation routines:

•    glTexGen*(…)

•    glEnable(GL_TEXTURE_GEN_*)

•    glDisable(GL_TEXTURE_GEN_*)

If you are multitexturing and specifying texture coordinates in vertex arrays, then glClientActiveTexture() directs the texture unit for which glTexCoordPointerQ specifies its texture-coordinate data.

void glClientActiveTexture(GLenum texUnit);

Selects the current texture unit for specifying texture-coordinate data with vertex arrays. texUnit is a symbolic constant of the form GL_TEXTUREi, with the same values that are used for glActiveTexture().

Reverting to a Single Texture Unit

If you are using multitexturing and want to return to a single texture unit, then you need to disable texturing for all units, except for texture unit 0, with code as shown in Example 9-12.

Example 9-12 Reverting to Texture Unit ()

Reverting to Texture Unit ()

Next post:

Previous post: