Textured objects can be viewed, like any other objects in a scene, at different
distances from the viewpoint. In a dynamic scene, as a textured object moves
farther from the viewpoint, the texture map must decrease in size along with
the size of the projected image. To accomplish this, OpenGL has to filter the
texture map down to an appropriate size for mapping onto the object, without
introducing visually disturbing artifacts. For example, to render a brick wall,
you may use a large (say 128x128 texel) texture image when it is close to the
viewer. But if the wall is moved farther away from the viewer until it appears
on the screen as a single pixel, then the filtered textures may appear to
change abruptly at certain transition points.
To avoid such artifacts, you can specify a series of prefiltered texture maps of decreasing resolutions, called mipmaps. The term mipmap was coined by Lance Williams, when he introduced the idea in his paper, "Pyramidal Parametrics" (SIGGRAPH 1983 Proceedings). Mip stands for the Latin multim im parvo, meaning "many things in a small place." Mipmapping uses some clever methods to pack image data into memory.
When using mipmapping, OpenGL automatically determines which texture map to use based on the size (in pixels) of the object being mapped. With this approach, the level of detail in the texture map is appropriate for the image that's drawn on the screen - as the image of the object gets smaller, the size of the texture map decreases. Mipmapping requires some extra computation and texture storage area; however, when it's not used, textures that are mapped onto smaller objects might shimmer and flash as the objects move.
To use mipmapping, you must provide all sizes of your texture in powers of 2 between the largest size and a 1x1 map. For example, if your highest-resolution map is 64x16, you must also provide maps of size 32x8, 16x4, 8x2, 4x1, 2x1, and 1x1. The smaller maps are typically filtered and averaged-down versions of the largest map in which each texel in a smaller texture is an average of the corresponding four texels in the larger texture.
To specify these textures, call glTexImage2D() once for each resolution of the texture map, with different values for the level, width, height, and image parameters. Starting with zero, level identifies which texture in the series is specified; with the previous example, the largest texture of size 64x16 would be declared with level = 0, the 32x8 texture with level = 1, and so on. In addition, for the mipmapped textures to take effect, you need to choose one of the appropriate filtering methods.
The construction of a series of such mipmaps is a software process, and thus isn't part of OpenGL, which is simply a rendering library. However, since mipmap construction is such an important operation, however, the OpenGL Utility Library contains two routines that aid in the manipulation of images to be used as mipmapped textures.
Assuming you have constructed the level 0, or highest-resolution map, the routines gluBuild1DMipmaps() and gluBuild2DMipmaps() construct and define the pyramid of mipmaps down to a resolution of 1x1 (or 1, for one-dimensional texture maps). If your original image has dimensions that are not exact powers of 2, gluBuild*DMipmaps() helpfully scales the image to the nearest power of 2.
int gluBuild1DMipmaps(
GLenum target,
GLint components,
GLint width,
GLenum format, GLenum type,
void *data);
int gluBuild2DMipmaps(
GLenum target,
GLint components,
GLint width, GLint height,
GLenum format, GLenum type,
void *data);
Constructs a series of mipmaps and calls glTexImage*D() to load the
images. The parameters for target,
components, width,
height, format, type, and
data are exactly the same as those for glTexImage1D()
and glTexImage2D(). A value of 0 is returned if all the mipmaps are
constructed successfully; otherwise, a GLU error code is returned.
Example:
// Create texture with all mipmap levels. glu.gluBuild2DMipmaps( target, GL.GL_RGB8, // Internal Texel Format, texture.getWidth(), texture.getHeight(), GL.GL_RGB, // External format from image, GL.GL_UNSIGNED_BYTE, texture.getPixels() // Imagedata );