The area of texture mapping is one of the more complex areas of the OpenGL API. It has been extended more often than most of the other areas of OpenGL primarily because this was the area of graphics for which hardware was the least mature when OpenGL was defined in the early 1990s. The programmability added through the OpenGL Shading Language in OpenGL 2.0 makes this area much more straightforward, but the existing OpenGL APIs are still used to create, modify, and define the behavior of textures. This section describes the texturing functionality as it existed for OpenGL 1.5. Some significant changes have been made to this model by OpenGL 2.0, particularly to the concept of texture units, and are described later in this book.
OpenGL currently supports four basic types of texture maps: onedimensional, two-dimensional, three-dimensional, and cube maps. (Only one- and two-dimensional textures were supported in OpenGL 1.0.) A 1D TEXTURE is an array containing width pixel values, a 2D TEXTURE is an array containing width x height pixel values, and a 3D TEXTURE is an array containing width x height x depth pixel values. A CUBE MAP TEXTURE contains six two-dimensional textures: one for each major axis direction (i.e., ±x, ±y, and ±z).
OpenGL has the notion of a TEXTURE UNIT. A texture unit corresponds to the underlying piece of graphics hardware that performs the various texturing operations. With OpenGL 1.3, support was added for multiple texture units. Each texture unit maintains the following state for performing texturing operations:
Commands to set the state in the preceding list operate on the ACTIVE TEXTURE UNIT. Texture units are numbered from 0 to GL_MAX_TEXTURE_UNITS 1 (a value that can be queried with glGet), and the active texture unit can be set with glActiveTexture with a symbolic constant indicating the desired texture unit. Subsequent commands to set state in the preceding list operate on only the active texture unit. A texture unit can be enabled for 1D, 2D, 3D, or cube map texturing by calling glEnable with the appropriate symbolic constant.
The active texture unit specifies the texture unit accessed by commands involving texture coordinate processing. Such commands include those accessing the current texture matrix stack (if GL_MATRIX_MODE is GL_TEXTURE), glTexGen, glEnable/glDisable (if any enumerated value for texture coordinate generation is selected), as well as queries of the current texture coordinates and current raster texture coordinates. The active texture unit selector also selects the texture unit accessed by commands involving texture image processing. Such commands include all variants of glTexEnv, glTexParameter, and glTexImage commands; glBindTexture; glEnable/glDisable for any texture target (e.g., GL_TEXTURE_2D); and queries of all such state.
A TEXTURE OBJECT is created as follows: call glBindTexture and provide a texture target (a symbolic constant that indicates whether the texture will be a 1D, 2D, 3D, or cube map texture) and a previously unused texture name (an integer other than zero) that can be used to refer to the newly created texture object. The newly created texture object also becomes active and is used in subsequent texturing operations. If glBindTexture is called with a texture name that has already been used, that previously created texture becomes active. In this way, an application can create any number of textures and switch between them easily.
After a texture object has been created, the pixel values that define the texture can be provided. Pixel values for a 3D texture can be supplied by glTexImage3D, pixel values for 2D or cube map textures can be provided by glTexImage2D, and pixel values for a 1D texture can be specified by glTexImage1D. In versions 1.01.5 of OpenGL, when any of these three commands was used, each dimension of the texture map had to be a size that was a power of 2 (including the border width). OpenGL 2.0 allows textures to have sizes that are not restricted to being powers of 2. These functions all work in the same way as glDrawPixels, except that the pixels constituting a texture are deposited into texture memory before rasterization. If only a portion of a texture needs to be respecified, the glTexSubImage1D/2D/3D functions can be used. When any of these three commands is used, there is no power-of-2 restriction on the texture size. Textures can be created or modified with values copied from frame buffer memory by glCopyTexImage1D/2D or glCopyTexSubImage1D/2D/3D.
OpenGL also provides a method for specifying textures with compressed image formats. Applications can use the commands glCompressedTexImage1D/2D/3D and glCompressedTexSubImage1D/2D/3D to create and store compressed textures in texture memory. Compressed textures may use significantly less memory on the graphics accelerator and thereby enhance an application's functionality or performance. Standard OpenGL does not define any particular compressed image formats, so applications need to query the extension string in order to determine the compressed texture formats supported by a particular implementation.
Each of the preceding texture creation commands includes a LEVEL-OF-DETAIL argument that supports the creation of MIPMAP TEXTURES. A mipmap texture is an ordered set of arrays representing the same image. Each array has a resolution that is half the previous one in each dimension. The idea behind mipmaps is that more pleasing final images will result if the texture to be used has roughly the same resolution as the object being drawn on the display. If a mipmap texture is supplied, OpenGL can automatically choose the appropriately sized texture (i.e., MIPMAP LEVEL) for use in drawing the object on the display. Interpolation between the TEXELS (pixels that comprise a texture) of two mipmap levels can also be performed. Objects that are textured with mipmap textures can therefore be rendered with high quality, no matter how they change size on the display.
After a texture object has been defined and bound to a texture unit, properties other than the pixels that define the texture can be modified with the command glTexParameter. This command sets parameters that control how the texture object is treated when it is specified, changed, or accessed. Texture object parameters include
The manner in which a texture value is applied to a graphics primitive is controlled by the parameters of the texture environment, which are set with the glTexEnv function. The set of fixed formulas for replacing an object color with a value computed through texture access is rather lengthy. Suffice it to say that texture functions include replacement, modulation, decal application, blending, adding, enabling point sprites, and even more complex combining of red, green, blue, and alpha components. A wide variety of texturing effects can be achieved with the flexibility provided by the glTexEnv function. This function can also specify an additional per-textureunit level-of-detail bias that is added to the per-texture-object level-of-detail bias previously described.
OpenGL supports the concept of multitexturing, by which the results of more than one texture access are combined to determine the value of the fragment. Each texture unit has a texture environment function. Texture units are connected serially. The first texture unit computes a fragment value by using the texture value that it reads from texture memory and its texture environment function, and passes on the result to be used as the input fragment value for the second texture unit. This fragment value is used together with the texture environment function for the second texture unit and the texture value read from texture memory by the second texture unit to provide the input fragment value for the third texture unit. This process is repeated for all enabled texture units.
After texture objects have been defined and one or more texture units have been properly set up and enabled, texturing is performed on all subsequent graphics primitives. Texture coordinates are supplied at each vertex with glTexCoord or glMultiTexCoord (for use with vertex-at-a-time entry points) or as an array indicated by glTexCoordPointer (for use with vertex array commands). The glMultiTexCoord command specifies texture coordinates that are to be operated on by a specific texture unit. This command specifies the texture unit as well as the texture coordinates to be used. The command glTexCoord is equivalent to the command glMultiTexCoord with its texture parameter set to GL_TEXTURE0. For vertex arrays, it is necessary to call glClientActiveTexture between each call to glTexCoordPointer in order to specify different texture coordinate arrays for different texture units.
Texture coordinates can also be generated automatically by OpenGL. Parameters for controlling automatic texture coordinate generation are set on a per-texture unit basis with the glTexGen command. This function lets the application select a texture generation function and supply coefficients for that function for the currently active texture unit. Supported texture generation functions are object linear (useful for automatically generating texture coordinates for terrain models), eye linear (useful for producing dynamic contour lines on moving objects), and sphere map (useful for a type of environment mapping that requires just one texture).
When texture coordinates have been sent to OpenGL or generated by the texture unit's texture generation function, they are transformed by the texture unit's current texture transformation matrix. The glMatrixMode command selects the texture matrix stack for modification, and subsequent matrix commands modify the texture matrix stack of the currently active texture unit. The current texture transformation matrix can translate the texture across the object, rotate it, stretch it, shrink it, and so on. Both texture generation and texture transformation are defined by OpenGL to occur as part of vertex processing (i.e., they are performed once per-vertex before rasterization).
TEXTURE ACCESS is the process by which the texture coordinates are used by a texture unit to access the enabled texture for that unit. It occurs after rasterization of the graphics primitive and interpolation of the transformed texture coordinates. The texture access is performed according to the bound texture object's parameters for filtering, wrapping, computed level-of-detail, and so on.
After a texture value has been retrieved, it is combined with the incoming color value according to the texture function established by calling glTexEnv. This operation is called TEXTURE APPLICATION. This computation produces a new fragment color value that is used for all subsequent processing of the fragment. Both texture access and texture application are defined to occur on every fragment that results from the rasterization process.