Chapter 8. Texture Mapping: The Basics

by Richard S. Wright, Jr.

WHAT YOU'LL LEARN IN THIS CHAPTER

How To

Functions You'll Use

Load texture images

glTexImage, glTexSubImage

Map textures to geometry

glTexCoord

Change the texture environment

glTexEnv

Set texture mapping parameters

glTexParameter

Generate mipmaps

gluBuildMipmaps

Manage multiple textures

glBindTexture

In the preceding chapter, we covered in detail the groundwork for loading image data into OpenGL. Image data, unless modified by pixel zoom, generally has a one-to-one correspondence between a pixel in an image to a pixel on the screen. In fact, this is where we get the term pixel (picture element). In this chapter, we extend this knowledge further by applying images to three-dimensional primitives. When we apply image data to a geometric primitive, we call this a texture or texture map. Figure 8.1 shows the dramatic difference that can be achieved by texture mapping geometry. The cube on the left is a lit and shaded featureless surface, whereas the cube on the right shows a richness in detail that can be reasonably achieved only with texture mapping.

The stark contrast between textured and untextured geometry.

Figure 8.1. The stark contrast between textured and untextured geometry.

A texture image when loaded has the same makeup and arrangement as pixmaps, but now a one-to-one correspondence seldom exists between texels (the individual picture elements in a texture) and pixels on the screen. This chapter covers the basics of loading a texture map into memory and all the ways in which it may be mapped to and applied to geometric primitives.

Loading Textures

The first necessary step in applying a texture map to geometry is to load the texture into memory. Once loaded, the texture becomes part of the current texture state (more on this later). Three OpenGL functions are most often used to load texture data from a memory buffer (which is, for example, read from a disk file):

void glTexImage1D(GLenum target, GLint level, GLint internalformat,
               GLsizei width, GLint border,
               GLenum format, GLenum type, void *data);

void glTexImage2D(GLenum target, GLint level, GLint internalformat,
               GLsizei width, GLsizei height, GLint border,
               GLenum format, GLenum type, void *data);

void glTexImage3D(GLenum target, GLint level, GLint internalformat,
               GLsizei width, GLsizei height, GLsizei depth, GLint border,
               GLenum format, GLenum type, void *data);

These three rather lengthy functions tell OpenGL everything it needs to know about how to interpret the texture data pointed to by the data parameter.

The first thing you should notice about these functions is that they are essentially three flavors of the same root function, glTexImage. OpenGL supports one-, two-, and three-dimensional texture maps and uses the corresponding function to load that texture and make it current. You should also be aware that OpenGL copies the texture information from data when you call one of these functions. This data copy can be quite expensive, and in the section “Texture Objects” we discuss some ways to help mitigate this problem.

The target argument for these functions should be GL_TEXTURE_1D, GL_TEXTURE_2D, or GL_TEXTURE_3D, respectively. You may also specify proxy textures in the same manner that you used proxies in the preceding chapter by specifying GL_PROXY_TEXTURE_1D, GL_PROXY_TEXTURE_2D, or GL_PROXY_TEXTURE_3D and using the function glGetTexParameter to retrieve the results of the proxy query.

The level parameter specifies the mipmap level being loaded. Mipmaps are covered in an upcoming section called “Mipmapping”, so for non-mipmapped textures (just your plain old ordinary texture mapping), always set this to 0 (zero) for the moment.

Next, you have to specify the internalformat parameter of the texture data. This information tells OpenGL how many color components you want stored per texel and possibly the storage size of the components and/or whether you want the texture compressed (see the next chapter for information about texture compression). Table 8.1 lists the most common values for this function. A complete listing is given in the reference section.

Table 8.1. Most Common Texture Internal Formats

Constant

Meaning

GL_ALPHA

Store the texels as alpha values

GL_LUMINANCE

Store the texels as luminance values

GL_LUMINANCE_ALPHA

Store the texels with both luminance and alpha values

GL_RGB

Store the texels as red, green, and blue components

GL_RGBA

Store the texels as red, green, blue, and alpha components

The width, height, and depth parameters (where appropriate) specify the dimensions of the texture being loaded. It is important to note that these dimensions must be integer powers of 2 (1, 2, 4, 8, 16, 32, 64, and so on). There is no requirement that texture maps be square (all dimensions equal), but a texture loaded with a nonpower of 2 dimensions will cause texturing to be implicitly disabled.

The border parameter allows you to specify a border width for texture maps. Texture borders allow you to extend the width, height, or depth of a texture map by an extra set of texels along the borders. Texture borders play an important role in the discussion of texture filtering to come. For the time being, always set this value to 0 (zero).

The last three parameters—format, type, and data—are identical to the corresponding arguments when you used glDrawPixels to place image data into the color buffer. For the sake of convenience, we listed the valid constants for format and type in Tables 8.2 and 8.3.

Table 8.2. Texel Formats for glTexImage

Constant

Description

GL_RGB

Colors are in red, green, blue order.

GL_RGBA

Colors are in red, green, blue, alpha order.

GL_BGR/GL_BGR_EXT

Colors are in blue, green, red order.

GL_BGRA/GL_BGRA_EXT

Colors are in blue, green, red, alpha order.

GL_RED

Each pixel contains a single red component.

GL_GREEN

Each pixel contains a single green component.

GL_BLUE

Each pixel contains a single blue component.

GL_ALPHA

Each pixel contains a single alpha component.

GL_LUMINANCE

Each pixel contains a single luminance (intensity) component.

GL_LUMINANCE_ALPHA

Each pixel contains a luminance followed by an alpha component.

GL_STENCIL_INDEX

Each pixel contains a single stencil index.

GL_DEPTH_COMPONENT

Each pixel contains a single depth component.

Table 8.3. Data Types for Pixel Data

Constant

Description

GL_UNSIGNED_BYTE

Each color component is an 8-bit unsigned integer

GL_BYTE

Signed 8-bit integer

GL_BITMAP

Single bits, no color data; same as glBitmap

GL_UNSIGNED_SHORT

Unsigned 16-bit integer

GL_SHORT

Signed 16-bit integer

GL_UNSIGNED_INT

Unsigned 32-bit integer

GL_INT

Signed 32-bit integer

GL_FLOAT

Single precision float

GL_UNSIGNED_BYTE_3_2_2

Packed RGB values

GL_UNSIGNED_BYTE_2_3_3_REV

Packed RGB values

GL_UNSIGNED_SHORT_5_6_5

Packed RGB values

GL_UNSIGNED_SHORT_5_6_5_REV

Packed RGB values

GL_UNSIGNED_SHORT_4_4_4_4

Packed RGBA values

GL_UNSIGNED_SHORT_4_4_4_4_REV

Packed RGBA values

GL_UNSIGNED_SHORT_5_5_5_1

Packed RGBA values

GL_UNSIGNED_SHORT_1_5_5_5_REV

Packed RGBA values

GL_UNSIGNED_INT_8_8_8_8

Packed RGBA values

GL_UNSIGNED_INT_8_8_8_8_REV

Packed RGBA values

GL_UNSIGNED_INT_10_10_10_2

Packed RGBA values

GL_UNSIGNED_INT_2_10_10_10_REV

Packed RGBA values

Loaded textures are not applied to geometry unless the appropriate texture state is enabled. You can call glEnable or glDisable with GL_TEXTURE_1D, GL_TEXTURE_2D, or GL_TEXTURE_3D to turn texturing on or off for a given texture state. Only one of these texture states may be on at a time for a given texture unit (see the next chapter for a discussion of multitexturing). However, it is good practice to turn unused texture states off when not in use. For example, to switch between one-dimensional and two-dimensional texturing, you would call

glDisable(GL_TEXTURE_1D);
glEnable(GL_TEXTURE_2D);

A final word about texture loading: Texture data loaded by the glTexImage functions goes through the same pixel and imaging pipeline covered in the preceding chapter. This means pixel packing, pixelzoom, color tables, convolutions, and so on are applied to the texture data when it is loaded.

Using the Color Buffer

One- and two-dimensional textures may also be loaded using data from the color buffer. You can read an image from the color buffer and use it as a new texture by using the following two functions:

void glCopyTexImage1D(GLenum target, GLint level, GLenum internalformat,
                                GLint x, GLint y,
                                GLsizei width, GLint border);

void glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat,
                                GLint x, GLint y,
                                GLsizei width, GLsizei height, GLint border);

These functions operate similarly to glTexImage, but in this case, x and y specify the location in the color buffer to begin reading the texture data. The source buffer is set using glReadBuffer and behaves just like glReadPixels.

Updating Textures

Repeatedly loading new textures can become a performance bottleneck in time-sensitive applications such as games or simulation applications. If a loaded texture map is no longer needed, it may be replaced entirely or in part. Replacing a texture map can often be done much quicker than reloading a new texture directly with glTexImage. The function you use to accomplish this is glTexSubImage, again in three variations:

void glTexSubImage1D(GLenum target, GLint level,
                                 GLint xOffset,
                                 GLsizei width,
                                 GLenum format, GLenum type, const GLvoid *data);
void glTexSubImage2D(GLenum target, GLint level,
                                 GLint xOffset, GLint yOffset,
                                 GLsizei width, GLsizei height,
                                 GLenum format, GLenum type, const GLvoid *data);

void glTexSubImage3D(GLenum target, GLint level,
                                 GLint xOffset, GLint yOffset, GLint zOffset,
                                 GLsizei width, GLsizei height, GLsizei depth,
                                 GLenum format, GLenum type, const GLvoid *data);

Most of the arguments correspond exactly to the parameters used in glTexImage. The xOffset, yOffset, and zOffset parameters specify the offsets into the existing texture map to begin replacing texture data. The width, height, and depth values specify the dimensions of the texture being “inserted” into the existing texture.

A final set of functions allows you to combine reading from the color buffer and inserting or replacing part of a texture. These glCopyTexSubImage variations do just that:

void glCopyTexSubImage1D(GLenum target, GLint level,
                                  GLint xoffset,
                                  GLint x, GLint y,
                                  GLsizei width);

void glCopyTexSubImage2D(GLenum target, GLint level,
                                  GLint xoffset, GLint yoffset,
                                  GLint x, GLint y,
                                  GLsizei width, GLsizei height);

void glCopyTexSubImage3D(GLenum target, GLint level,
                                  GLint xoffset, GLint yoffset, Glint zoffset,
                                  GLint x, GLint y,
                                  GLsizei width, GLsizei height);

You may have noticed that no glCopyTexImage3D function is listed here. The reason is that the color buffer is 2D, and there simply is no corresponding way to use a 2D color image as a source for a 3D texture. However, you can use glCopyTexSubImage3D to use the color buffer data to set a plane of texels in a three-dimensional texture.

Mapping Textures to Geometry

Loading a texture and enabling texturing cause OpenGL to apply the texture to any of the OpenGL primitives. You must, however, provide OpenGL with information about how to map the texture to the geometry. You do this by specifying a texture coordinate for each vertex. Texels in a texture map are addressed not as a memory location (as you would for pixmaps), but as a more abstract (usually floating-point values) texture coordinate. Typically, texture coordinates are specified as floating-point values that are clamped in the range 0.0 to 1.0. Texture coordinates are named s, t, r, and q (similar to vertex coordinates x, y, z, and w) supporting from one- to three-dimensional texture coordinates, and optionally a way to scale the coordinates.

Figure 8.2 shows one-, two-, and three-dimensional textures and the way the texture coordinates are laid out with respect to their texels.

How texture coordinates address texels.

Figure 8.2. How texture coordinates address texels.

Because there are no four-dimensional textures, you might ask what the q coordinate is for. The q coordinate corresponds to the w geometric coordinate. This is a scaling factor applied to the other texture coordinates; that is, the actual values used for the texture coordinates are s/q, t/q, and r/q. By default, q is set to 1.0.

You specify a texture coordinate using the glTexCoord function. Much like vertex coordinates, surface normals, and color values, this function comes in a variety of familiar flavors that are all listed in the reference section. The following are three simple variations used in the sample programs:

void glTexCoord1f(GLfloat s);
void glTexCoord2f(Glfloat s, GLfloat t);
void glTexCoord3f(GLfloat s, GLfloat t, GLfloat r);

One texture coordinate is applied using these functions for each vertex. OpenGL then stretches or shrinks the texture as necessary to apply the texture to the geometry as mapped. (This stretching or shrinking is applied using the current texture filter; we discuss this issue shortly as well.) Figure 8.3 shows an example of a two-dimensional texture being mapped to a GL_QUAD. Note the corners of the texture correspond to the corners of the quad. As you do with other vertex properties (materials, normals, and so on), you must specify the texture coordinate before the vertex!

Applying a two-dimensional texture to a quad.

Figure 8.3. Applying a two-dimensional texture to a quad.

Rarely, however, do you have such a nice fit of a square texture mapped to a square piece of geometry. To help you better understand texture coordinates, we provide another example in Figure 8.4. This figure also shows a square texture map, but the geometry is a triangle. Superimposed on the texture map are the texture coordinates of the locations in the map being extended to the vertices of the triangle.

Applying a portion of a texture map to a triangle.

Figure 8.4. Applying a portion of a texture map to a triangle.

Texture Matrix

Texture coordinates can also be transformed via the texture matrix. The texture matrix stack works just like the other matrices previously discussed (modelview, projection, and color). You make the texture matrix the target of matrix function calls by calling glMatrixMode with the argument GL_TEXTURE:

glMatrixMode(GL_TEXTURE);

The texture matrix stack is required to be only two elements deep for the purposes of glPushMatrix and glPopMatrix. Texture coordinates can be translated, scaled, and even rotated.

A Simple 2D Example

Loading a texture and providing texture coordinates are the fundamental requirements for texture mapping. There are a number of issues we have yet to address, such as coordinate wrapping, texture filters, and the texture environment. What do they mean, and how do we make use of them? Let's pause here first and examine a simple example that uses a 2D texture. In the code that follows, we use the functions covered so far and add several new ones. We use this example, then, as a framework to describe these additional texture mapping issues.

Listing 8.1 shows all the code for the sample program PYRAMID. This program draws a simple lit four-sided pyramid made up of triangles. A stone texture is applied to each face and the bottom of the pyramid. You can spin the pyramid around with the arrow keys much like the samples in earlier chapters. Figure 8.5 shows the output of the PYRAMID program.

Example 8.1. The PYRAMID Sample Program Source Code

// Pyramid.c
// Demonstrates Simple Texture Mapping
// OpenGL SuperBible
// Richard S. Wright Jr.
#include "../../Common/OpenGLSB.h"  // System and OpenGL Stuff
#include "../../Common/GLTools.h"   // GLTools

// Rotation amounts
static GLfloat xRot = 0.0f;
static GLfloat yRot = 0.0f;


// Change viewing volume and viewport.  Called when window is resized
void ChangeSize(int w, int h)
    {
    GLfloat fAspect;

    // Prevent a divide by zero
    if(h == 0)
        h = 1;

    // Set Viewport to window dimensions
    glViewport(0, 0, w, h);

    fAspect = (GLfloat)w/(GLfloat)h;

    // Reset coordinate system
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    // Produce the perspective projection
    gluPerspective(35.0f, fAspect, 1.0, 40.0);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    }


// This function does any needed initialization on the rendering
// context.  Here it sets up and initializes the lighting for
// the scene.
void SetupRC()
    {
    GLubyte *pBytes;
    GLint iWidth, iHeight, iComponents;
    GLenum eFormat;

    // Light values and coordinates
    GLfloat  whiteLight[] = { 0.05f, 0.05f, 0.05f, 1.0f };
    GLfloat  sourceLight[] = { 0.25f, 0.25f, 0.25f, 1.0f };
    GLfloat  lightPos[] = { -10.f, 5.0f, 5.0f, 1.0f };

    glEnable(GL_DEPTH_TEST);  // Hidden surface removal
    glFrontFace(GL_CCW);      // Counter clock-wise polygons face out
    glEnable(GL_CULL_FACE);   // Do not calculate inside of jet

    // Enable lighting
    glEnable(GL_LIGHTING);

    // Setup and enable light 0
    glLightModelfv(GL_LIGHT_MODEL_AMBIENT,whiteLight);
    glLightfv(GL_LIGHT0,GL_AMBIENT,sourceLight);
    glLightfv(GL_LIGHT0,GL_DIFFUSE,sourceLight);
    glLightfv(GL_LIGHT0,GL_POSITION,lightPos);
    glEnable(GL_LIGHT0);

    // Enable color tracking
    glEnable(GL_COLOR_MATERIAL);

    // Set Material properties to follow glColor values
    glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);

    // Black blue background
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f );

    // Load texture
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    pBytes = gltLoadTGA("Stone.tga", &iWidth, &iHeight,
                                              &iComponents, &eFormat);
    glTexImage2D(GL_TEXTURE_2D, 0, iComponents, iWidth, iHeight,
                                0, eFormat, GL_UNSIGNED_BYTE, pBytes);
    free(pBytes);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    glEnable(GL_TEXTURE_2D);
    }

// Respond to arrow keys
void SpecialKeys(int key, int x, int y)
    {
    if(key == GLUT_KEY_UP)
        xRot-= 5.0f;

    if(key == GLUT_KEY_DOWN)
        xRot += 5.0f;

    if(key == GLUT_KEY_LEFT)
        yRot -= 5.0f;

    if(key == GLUT_KEY_RIGHT)
        yRot += 5.0f;

        xRot = (GLfloat)((const int)xRot % 360);
        yRot = (GLfloat)((const int)yRot % 360);

    // Refresh the Window
    glutPostRedisplay();
    }


// Called to draw scene
void RenderScene(void)
    {
    GLTVector3 vNormal;
    GLTVector3 vCorners[5] = { { 0.0f, .80f, 0.0f },     // Top           0
                              { -0.5f, 0.0f, -.50f },    // Back left     1
                              { 0.5f, 0.0f, -0.50f },    // Back right    2
                              { 0.5f, 0.0f, 0.5f },      // Front right   3
                              { -0.5f, 0.0f, 0.5f }};    // Front left    4

    // Clear the window with current clearing color
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Save the matrix state and do the rotations
    glPushMatrix();
        // Move object back and do in place rotation
        glTranslatef(0.0f, -0.25f, -4.0f);
        glRotatef(xRot, 1.0f, 0.0f, 0.0f);
        glRotatef(yRot, 0.0f, 1.0f, 0.0f);

        // Draw the Pyramid
        glColor3f(1.0f, 1.0f, 1.0f);
        glBegin(GL_TRIANGLES);
            // Bottom section - two triangles
            glNormal3f(0.0f, -1.0f, 0.0f);
            glTexCoord2f(1.0f, 1.0f);
            glVertex3fv(vCorners[2]);

            glTexCoord2f(0.0f, 0.0f);
            glVertex3fv(vCorners[4]);

            glTexCoord2f(0.0f, 1.0f);
            glVertex3fv(vCorners[1]);


            glTexCoord2f(1.0f, 1.0f);
            glVertex3fv(vCorners[2]);

            glTexCoord2f(1.0f, 0.0f);
            glVertex3fv(vCorners[3]);

            glTexCoord2f(0.0f, 0.0f);
            glVertex3fv(vCorners[4]);

            // Front Face
            gltGetNormalVector(vCorners[0], vCorners[4], vCorners[3], vNormal);
            glNormal3fv(vNormal);
            glTexCoord2f(0.5f, 1.0f);
            glVertex3fv(vCorners[0]);
            glTexCoord2f(0.0f, 0.0f);
            glVertex3fv(vCorners[4]);
            glTexCoord2f(1.0f, 0.0f);
            glVertex3fv(vCorners[3]);

            // Left Face
            gltGetNormalVector(vCorners[0], vCorners[1], vCorners[4], vNormal);
            glNormal3fv(vNormal);
            glTexCoord2f(0.5f, 1.0f);
            glVertex3fv(vCorners[0]);
            glTexCoord2f(0.0f, 0.0f);
            glVertex3fv(vCorners[1]);
            glTexCoord2f(1.0f, 0.0f);
            glVertex3fv(vCorners[4]);

            // Back Face
            gltGetNormalVector(vCorners[0], vCorners[2], vCorners[1], vNormal);
            glNormal3fv(vNormal);
            glTexCoord2f(0.5f, 1.0f);
            glVertex3fv(vCorners[0]);

            glTexCoord2f(0.0f, 0.0f);
            glVertex3fv(vCorners[2]);

            glTexCoord2f(1.0f, 0.0f);
            glVertex3fv(vCorners[1]);

            // Right Face
            gltGetNormalVector(vCorners[0], vCorners[3], vCorners[2], vNormal);
            glNormal3fv(vNormal);
            glTexCoord2f(0.5f, 1.0f);
            glVertex3fv(vCorners[0]);
            glTexCoord2f(0.0f, 0.0f);
            glVertex3fv(vCorners[3]);
            glTexCoord2f(1.0f, 0.0f);
            glVertex3fv(vCorners[2]);
        glEnd();


    // Restore the matrix state
    glPopMatrix();

    // Buffer swap
    glutSwapBuffers();
    }


int main(int argc, char *argv[])
    {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(800, 600);
    glutCreateWindow("Textured Pyramid");
    glutReshapeFunc(ChangeSize);
    glutSpecialFunc(SpecialKeys);
    glutDisplayFunc(RenderScene);
    SetupRC();
    glutMainLoop();

    return 0;
    }
Output from the PYRAMID sample program.

Figure 8.5. Output from the PYRAMID sample program.

The SetupRC function does all the necessary initialization for this program, including loading the texture using the gltLoadTGA function presented in the preceding chapter and supplying the bits to the glTexImage2D function:

// Load texture
pBytes = gltLoadTGA("Stone.tga", &iWidth, &iHeight,
                                          &iComponents, &eFormat);
glTexImage2D(GL_TEXTURE_2D, 0, iComponents, iWidth, iHeight,
                            0, eFormat, GL_UNSIGNED_BYTE, pBytes);
free(pBytes);

Of course, texture mapping must also be turned on:

glEnable(GL_TEXTURE_2D);

The RenderScene function draws the pyramid as a series of texture-mapped triangles. The following excerpt shows one face being constructed as a normal (calculated using the corner vertices) is specified for the face, followed by three texture and vertex coordinates:

// Front Face
gltGetNormalVector(vCorners[0], vCorners[4], vCorners[3], vNormal);
glNormal3fv(vNormal);
glTexCoord2f(0.5f, 1.0f);
glVertex3fv(vCorners[0]);
glTexCoord2f(0.0f, 0.0f);
glVertex3fv(vCorners[4]);
glTexCoord2f(1.0f, 0.0f);
glVertex3fv(vCorners[3]);

Texture Environment

In the PYRAMID sample program, the pyramid is drawn with white material properties, and the texture is applied in such a way that its colors are scaled by the coloring of the lit geometry. Figure 8.6 shows the untextured pyramid alongside the source texture and the textured but shaded pyramid.

Lit Geometry + Texture = Shaded Texture.

Figure 8.6. Lit Geometry + Texture = Shaded Texture.

How OpenGL combines the colors from texels with the color of the underlying geometry is controlled by the texture environment mode. You set this mode by calling the glTexEnv function:

void glTexEnvi(GLenum target, GLenum pname, GLint param);
void glTexEnvf(GLenum target, GLenum pname, GLfloat param);
void glTexEnviv(GLenum target, GLenum pname, GLint *param);
void glTexEnvfv(GLenum target, GLenum pname, GLfloat *param);

This function comes in a variety of flavors, as shown here, and controls a number of more advanced texturing options covered in the next chapter. In the PYRAMID sample program, this function set the environment mode to GL_MODULATE before any texture application was performed:

glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

The modulate environment mode multiplies the texel color by the geometry color (after lighting calculations). This is why the shaded color of the pyramid comes through and makes the texture appear to be shaded. Using this mode, you can change the color tone of textures by using colored geometry. For example, a black-and-white brick texture applied to red, yellow, and brown geometry would yield red, yellow, and brown bricks with only a single texture.

If you want to simply replace the color of the underlying geometry, you can specify GL_REPLACE for the environment mode. Doing so replaces fragment colors from the geometry directly with the texel colors. Making this change eliminates any effect on the texture from the underlying geometry. If the texture has an alpha channel, you can enable blending, and you can use this mode to create transparent geometry patterned after the alpha channel in the texture map.

If the texture doesn't have an alpha component, GL_DECAL behaves the same way as GL_REPLACE. It simply “decals” the texture over the top of the geometry and any color values that have been calculated for the fragments. However, if the texture has an alpha component, the decal can be applied in such a way that the geometry shows through where the alpha is blended with the underlying fragments.

Textures can also be blended with a constant blending color using the GL_BLEND texture environment. If you set this environment mode, you must also set the texture environment color:

GLfloat fColor[4] = { 1.0f, 0.0f, 0.0f, 0.0f };
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, fColor);

Finally, you can simply add texel color values to the underlying fragment values by setting the environment mode to GL_ADD. Any color component values that exceed 1.0 are clamped, and you may get saturated color values (basically, white or closer to white than you might intend).

We have not presented an exhaustive list of the texture environment constants here. See the reference section and next chapter for more modes and texturing effects that are enabled and controlled through this function. We also revisit some additional uses in coming sections and sample programs.

Texture Parameters

More effort is involved in texture mapping than slapping an image on the side of a triangle. Many parameters affect the rendering rules and behaviors of texture maps as they are applied. These texture parameters are all set via variations on the function glTexParameter:

void glTexParameterf(GLenum target, GLenum pname, GLfloat param);
void glTexParameteri(GLenum target, GLenum pname, GLint param);
void glTexParameterfv(GLenum target, GLenum pname, GLfloat *params);
void glTexParameteriv(GLenum target, GLenum pname, GLint *params);

The first argument, target, specifies which texture mode the parameter is to be applied to and may be either GL_TEXTURE_1D, GL_TEXTURE_2D, or GL_TEXTURE_3D. The second argument, pname, specifies which texture parameter is being set, and finally, the param or params arguments set the value of the particular texture parameter.

Basic Filtering

Unlike pixmaps being drawn to the color buffer, when a texture is applied to geometry, there is almost never a one-to-one correspondence between texels in the texture map and pixels on the screen. A careful programmer could achieve this result, but only by texturing geometry that was carefully planned to appear onscreen such that the texels and pixels lined up. Consequently, texture images are always either stretched or shrunk as they are applied to geometric surfaces. Because of the orientation of the geometry, a given texture could even be stretched and shrunk at the same time across the surface of some object.

The process of calculating color fragments from a stretched or shrunken texture map is called texture filtering. Using the texture parameter function, OpenGL allows you to set both magnification and minification filters. The parameter names for these two filters are GL_TEXTURE_MAG_FILTER and GL_TEXTURE_MIN_FILTER. You can select two basic texture filters for them, GL_NEAREST and GL_LINEAR, which correspond to nearest neighbor and linear filtering.

Nearest neighbor filtering is the simplest and fastest filtering method you can choose. Texture coordinates are evaluated and plotted against a texture's texels, and whichever texel the coordinate falls in, that color is used for the fragment texture color. Nearest neighbor filtering is characterized by large blocky pixels when the texture is stretched especially large. An example is shown in Figure 8.7. You can set the texture filter (for GL_TEXTURE_2D) for both the minification and magnification filter by using these two function calls:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
Nearest neighbor filtering up close.

Figure 8.7. Nearest neighbor filtering up close.

Linear filtering requires more work than nearest neighbor, but often is worth the extra overhead. On today's commodity hardware, the extra cost of linear filtering is negligible. Linear filtering works by not taking the nearest texel to the texture coordinate, but by applying the weighted average of the texels surrounding the texture coordinate (a linear interpolation). For this interpolated fragment to match the texel color exactly, the texture coordinate needs to fall directly in the center of the texel. Linear filtering is characterized by “fuzzy” graphics when a texture is stretched. This fuzziness, however, often lends to a more realistic and less artificial look than the jagged blocks of the nearest neighbor filtering mode. A contrasting example to Figure 8.7 is shown in Figure 8.8. You can set linear filtering (for GL_TEXTURE_2D) simply enough by using the following lines, which are also included in the SetupRC function in the PYRAMID example:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
Linear filtering up close.

Figure 8.8. Linear filtering up close.

Texture Wrap

Normally, you specify texture coordinates between 0.0 and 1.0 to map out the texels in a texture map. If texture coordinates fall outside this range, OpenGL handles them according to the current texture wrapping mode. You can set the wrap mode for each coordinate individually by calling glTexParameteri with GL_TEXTURE_WRAP_S, GL_TEXTURE_WRAP_T, or GL_TEXTURE_WRAP_R as the parameter name. The wrap mode can then be set to one of the following values: GL_REPEAT, GL_CLAMP, GL_CLAMP_TO_EDGE, or GL_CLAMP_TO_BORDER.

The GL_REPEAT wrap mode simply causes the texture to repeat in the direction in which the texture coordinate has exceeded 1.0. The texture repeats again for every integer texture coordinate. This mode is very useful for applying a small tiled texture to large geometric surfaces. Well-done seamless textures can lend the appearance of a seemingly much larger texture, but at the cost of a much smaller texture image. The other modes do not repeat, but are “clamped”—thus their name.

If the only implication of the wrap mode is whether the texture repeats, you would need only two wrap modes: repeat and clamp. However, the texture wrap mode also has a great deal of influence on how texture filtering is done at the edges of the texture maps. For GL_NEAREST filtering, there are no consequences to the wrap mode because the texture coordinates are always snapped to some particular texel within the texture map. However, the GL_LINEAR filter takes an average of the pixels surrounding the evaluated texture coordinate, and this creates a problem for texels that lie along the edges of the texture map.

This problem is resolved quite neatly when the wrap mode is GL_REPEAT. The texel samples are simply taken from the next row or column, which in repeat mode wraps back around to the other side of the texture. This mode works perfectly for textures that wrap around an object and meet on the other side (such as spheres).

The clamped texture wrap modes offer a number of options for the way texture edges are handled. For GL_CLAMP, the needed texels are taken from the texture border or the TEXTURE_BORDER_COLOR (set with glTexParameterfv). The GL_CLAMP_TO_EDGE wrap mode simply ignores texel samples that go over the edge and does not include them in the average. Finally, GL_CLAMP_TO_BORDER uses only border texels whenever the texture coordinates fall outside the range 0.0 to 1.0.

A typical application of the clamped modes occurs when you must texture a large area that would require a single texture too large to fit into memory, or that may be loaded into a single texture map. In this case, the area is chopped up into smaller “tiles” that are then placed side by side. In such a case, not using a wrap mode such as GL_CLAMP_TO_EDGE causes visible filtering artifacts along the seams between tiles.

In the PYRAMID sample program, texture coordinates along the bottom of the pyramid might leave a dark seam, except that you have set the wrap mode to clamp the bilinear filtering to within the texture map:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

Cartoons with Texture

The first example for this chapter used 2D textures because they are usually the simplest and easiest to understand. Most people can quickly get an intuitive feel for putting a 2D picture on the side of a piece of 2D geometry (such as a triangle). We will step back now and present a one-dimensional texture mapping example that is commonly used in computer games to render geometry that appears onscreen shaded like a cartoon. Toon-shading, which is often referred to as cell-shading, uses a one-dimensional texture map as a lookup table to fill in geometry with a solid color (using GL_NEAREST) from the texture map.

The basic idea is to use a surface normal from the geometry and a normal from the light source to find the intensity of the light striking the surface of the model. The dot product of these two vectors gives a value between 0.0 and 1.0 and is used as a one-dimensional texture coordinate. The sample program TOON presented in Listing 8.2 draws a green torus using this technique. The output from TOON is shown in Figure 8.9.

Example 8.2. Source Code for the TOON Sample Program

// Toon.c
// OpenGL SuperBible
// Demonstrates Cell/Toon shading with a 1D texture
// Program by Richard S. Wright Jr.

#include "../../Common/OpenGLSB.h"    // System and OpenGL Stuff
#include "../../Common/GLTools.h"     // OpenGL toolkit
#include <math.h>

// Draw a torus (doughnut), using the current 1D texture for light shading
void toonDrawTorus(GLfloat majorRadius, GLfloat minorRadius,
                             int numMajor, int numMinor, GLTVector3 vLightDir)
    {
    GLTMatrix mModelViewMatrix;
    GLTVector3 vNormal, vTransformedNormal;
    double majorStep = 2.0f*GLT_PI / numMajor;
    double minorStep = 2.0f*GLT_PI / numMinor;
    int i, j;

    // Get the modelview matrix
    glGetFloatv(GL_MODELVIEW_MATRIX, mModelViewMatrix);

    // Normalize the light vector
    gltNormalizeVector(vLightDir);

    // Draw torus as a series of triangle strips
    for (i=0; i<numMajor; ++i)
        {
        double a0 = i * majorStep;
        double a1 = a0 + majorStep;
        GLfloat x0 = (GLfloat) cos(a0);
        GLfloat y0 = (GLfloat) sin(a0);
        GLfloat x1 = (GLfloat) cos(a1);
        GLfloat y1 = (GLfloat) sin(a1);

        glBegin(GL_TRIANGLE_STRIP);
        for (j=0; j<=numMinor; ++j)
            {
            double b = j * minorStep;
            GLfloat c = (GLfloat) cos(b);
            GLfloat r = minorRadius * c + majorRadius;
            GLfloat z = minorRadius * (GLfloat) sin(b);

            // First point
            vNormal[0] = x0*c;
            vNormal[1] = y0*c;
            vNormal[2] = z/minorRadius;
            gltNormalizeVector(vNormal);
            gltRotateVector(vNormal, mModelViewMatrix, vTransformedNormal);

            // Texture coordinate is set by intensity of light
            glTexCoord1f(gltVectorDotProduct(vLightDir, vTransformedNormal));
            glVertex3f(x0*r, y0*r, z);

            // Second point
            vNormal[0] = x1*c;
            vNormal[1] = y1*c;
            vNormal[2] = z/minorRadius;
            gltNormalizeVector(vNormal);
            gltRotateVector(vNormal, mModelViewMatrix, vTransformedNormal);

            // Texture coordinate is set by intensity of light
            glTexCoord1f(gltVectorDotProduct(vLightDir, vTransformedNormal));
            glVertex3f(x1*r, y1*r, z);
            }
        glEnd();
        }
    }


// Called to draw scene
void RenderScene(void)
    {
    // Rotation angle
    static GLfloat yRot = 0.0f;

    // Where is the light coming from
    GLTVector3 vLightDir = { -1.0f, 1.0f, 1.0f };

    // Clear the window with current clearing color
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glPushMatrix();
        glTranslatef(0.0f, 0.0f, -2.5f);
        glRotatef(yRot, 0.0f, 1.0f, 0.0f);
        toonDrawTorus(0.35f, 0.15f, 50, 25, vLightDir);
    glPopMatrix();

    // Do the buffer Swap
    glutSwapBuffers();

    // Rotate 1/2 degree more each frame
    yRot += 0.5f;
    }

// This function does any needed initialization on the rendering
// context.
void SetupRC()
    {
    // Load a 1D texture with toon shaded values
    // Green, greener...
    GLbyte toonTable[4][3] = { { 0, 32, 0 },
                               { 0, 64, 0 },
                               { 0, 128, 0 },
                               { 0, 192, 0 }};

    // Bluish background
    glClearColor(0.0f, 0.0f, .50f, 1.0f );
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_CULL_FACE);

    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
    glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, 4, 0, GL_RGB,
                     GL_UNSIGNED_BYTE, toonTable);

    glEnable(GL_TEXTURE_1D);
    }

///////////////////////////////////////////////////////////
// Called by GLUT library when idle (window not being
// resized or moved)
void TimerFunction(int value)
    {
    // Redraw the scene with new coordinates
    glutPostRedisplay();
    glutTimerFunc(33,TimerFunction, 1);
    }


void ChangeSize(int w, int h)
    {
    GLfloat fAspect;

    // Prevent a divide by zero, when window is too short
    // (you can't make a window of zero width).
    if(h == 0)
        h = 1;

    glViewport(0, 0, w, h);

    fAspect = (GLfloat)w / (GLfloat)h;

    // Reset the coordinate system before modifying
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    // Set the clipping volume
    gluPerspective(35.0f, fAspect, 1.0f, 50.0f);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    }

///////////////////////////////////////////////////
// Program entry point
int main(int argc, char* argv[])
    {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(800,600);
    glutCreateWindow("Toon/Cell Shading Demo");
    glutReshapeFunc(ChangeSize);
    glutDisplayFunc(RenderScene);
    glutTimerFunc(33, TimerFunction, 1);

    SetupRC();
    glutMainLoop();

    return 0;
    }
A cell-shaded torus.

Figure 8.9. A cell-shaded torus.

Mipmapping

Mipmapping”is a powerful texturing technique that can improve both the rendering performance and visual quality of a scene. It does this by addressing two common problems with standard texture mapping. The first is an effect called scintillation (aliasing artifacts) that appears on the surface of objects rendered very small onscreen compared to the relative size of the texture applied. Scintillation can be seen as a sort of sparkling that occurs as the sampling area on a texture map moves disproportionately to its size on the screen. The negative effects of scintillation are most noticeable when the camera or the objects are in motion.

The second issue is more performance related, but is due to the same scenario that leads to scintillation. That is, a large amount of texture memory must be loaded and processed through filtering to display a small number of fragments onscreen. This causes texturing performance to suffer greatly as the size of the texture increases.

The solution to both of these problems is to simply use a smaller texture map. However, this solution then creates a new problem, that when near the same object, it must be rendered larger, and a small texture map will then be stretched to the point of creating a hopelessly blurry or blocky textured object.

The solution to both of these issues is mipmapping. Mipmapping”gets its name from the Latin phrase multum in parvo, which means “many things in a small place.” In essence, you load not a single image into the texture state, but a whole series of images from largest to smallest into a single “mipmapped” texture state. OpenGL then uses a new set of filter modes to choose the best-fitting texture or textures for the given geometry. At the cost of some extra memory (and possibly considerably more processing work), you can eliminate scintillation and the texture memory processing overhead for distant objects simultaneously, while maintaining higher resolution versions of the texture available when needed.

A mipmapped texture consists of a series of texture images, each one half the size of the previous image. This scenario is shown in Figure 8.10. Mipmap levels do not have to be square, but the halving of the dimensions continues until the last image is 1×1 texel. When one of the dimensions reaches 1, further divisions occur on the other dimension only. Using a square set of mipmaps requires about one third more memory than not using mipmaps.

A series of mipmapped images.

Figure 8.10. A series of mipmapped images.

Mipmap levels are loaded with glTexImage. Now the level parameter comes into play because it specifies which mip level the image data is for. The first level is 0, then 1, 2, and so on. If mipmapping”is not being used, only level 0 is ever loaded. By default, to use mipmaps, all mip levels must be populated. You can, however, specifically set the base and maximum levels to be used with the GL_TEXTURE_BASE_LEVEL and GL_TEXTURE_MAX_LEVEL texture parameters. For example, if you want to specify that only mip levels 0 through 4 need to be loaded, you call glTexParameteri twice as follows:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 4);

Although GL_TEXTURE_BASE_LEVEL and GL_TEXTURE_MAX_LEVEL control which mip levels are loaded, you can also specifically limit the range of loaded mip levels to be used by using the parameters GL_TEXTURE_MIN_LOD and GL_TEXTURE_MAX_LOD instead.

Mipmap Filtering

Mipmapping adds a new twist to the two basic texture filtering modes GL_NEAREST and GL_LINEAR by giving four permutations for mipmapped filtering modes. They are listed in Table 8.4.

Table 8.4. Mipmapped Texture Filters

Constant

Description

GL_NEAREST

Perform nearest neighbor filtering on the base mip level

GL_LINEAR

Perform linear filtering on the base mip level

GL_NEAREST_MIPMAP_NEAREST

Select the nearest mip level and perform nearest neighbor filtering

GL_NEAREST_MIPMAP_LINEAR

Perform a linear interpolation between mip levels and perform nearest neighbor filtering

GL_LINEAR_MIPMAP_NEAREST

Select the nearest mip level and perform linear filtering

GL_LINEAR_MIPMAP_LINEAR

Perform a linear interpolation between mip levels and perform linear filtering; also called trilinear mipmapping

Just loading the mip levels with glTexImage does not by itself enable mipmapping. If the texture filter is set to GL_LINEAR or GL_NEAREST, only the base texture level is used, and any mip levels loaded are ignored. You must specify one of the mipmapped filters listed for the loaded mip levels to be used. The constants have the form GL_FILTER_MIPMAP_SELECTOR, where FILTER specifies the texture filter to be used on the mip level selected. The SELECTOR specifies how the mip level is selected; for example, GL_NEAREST selects the nearest matching mip level. Using GL_LINEAR for the selector creates a linear interpolation between the two nearest mip levels, which is again filtered by the chosen texture filter. Selecting one of the mipmapped filtering modes without loading the mip levels has the effect of disabling texture mapping.

Which filter you select varies depending on the application and the performance requirements at hand. GL_NEAREST_MIPMAP_NEAREST, for example, gives very good performance and low aliasing (scintillation) artifacts, but nearest neighbor filtering is often not visually pleasing. GL_LINEAR_MIPMAP_NEAREST is often used to speed up games because a higher quality linear filter is used, but a fast selection (nearest) is made between the different sized mip levels available.

Using nearest as the mipmap selector (as in both examples in the preceding paragraph), however, can also leave an undesirable visual artifact. For oblique views, you can often see the transition from one mip level to another across a surface. It can be seen as a distortion line or a sharp transition from one level of detail to another. The GL_LINEAR_MIPMAP_LINEAR and GL_NEAREST_MIPMAP_LINEAR filters perform an additional interpolation between mip levels to eliminate this transition zone, but at the extra cost of substantially more processing overhead. The GL_LINEAR_MIPMAP_LINEAR filter is often referred to as trilinear mipmapping”and until recently was the gold standard (highest fidelity) of texture filtering. More recently, anisotropic texture filtering (covered in the next chapter) has become widely available on OpenGL hardware but even further increases the cost (performance wise) of texture mapping.

Generating Mip Levels

As mentioned previously, mipmapping”requires approximately one third more texture memory than just loading the base texture image. It also requires that all the smaller versions of the base texture image be available for loading. Sometimes this can be inconvenient because the lower resolution images may not necessarily be available either to the programmer or the end user of your software. The GLU library does include a function named gluScaleImage (see the reference section) that you could use to repeatedly scale and load an image until all the needed mip levels are loaded. More frequently, however, an even more convenient function is available; it automatically creates the scaled images for you and loads them appropriately with glTexImage. This function, gluBuildMipmaps, comes in three flavors and supports one-, two-, and three-dimensional texture maps:

int gluBuild1DMipmaps(GLenum target, GLint internalFormat,
                                 GLint width,
                                 GLenum format, GLenum type, const void *data);

int gluBuild2DMipmaps(GLenum target, GLint internalFormat,
                                 GLint width, GLint height,
                                 GLenum format, GLenum type, const void *data);

int gluBuild3DMipmaps(GLenum target, GLint internalFormat,
                                 GLint width, GLint height, GLint depth,
                                 GLenum format, GLenum type, const void *data);

The use of these functions closely parallels the use of glTexImage, but they do not have a level parameter for specifying the mip level, nor do they provide any support for a texture border. You should also be aware that using these functions may not produce mip level images with the same quality you can obtain with other tools such as Photoshop. The GLU library uses a box filter to reduce images, which can lead to an undesirable loss of fine detail as the image shrinks.

With newer versions of the GLU library, you can also obtain a finer-grained control over which mip levels are loaded with these functions:

int gluBuild1DMipmapLevels(GLenum target, GLint internalFormat,
                                      GLint width,
                                      GLenum format, GLenum type, GLint level,
                                      GLint base, GLint max, const void *data);

int gluBuild2DMipmapLevels(GLenum target, GLint internalFormat,
                                      GLint width, GLint height,
                                      GLenum format, GLenum type, GLint level,
                                      GLint base, GLint max, const void *data);

int gluBuild3DMipmapLevels(GLenum target, Glint internalFormat,
                                      GLint width, GLint height, GLint depth,
                                      GLenum format, GLenum type, GLint level,
                                      GLint base, GLint max, const void *data);

With these functions, level is the mip level specified by the data parameter. This texture data is used to build mip levels base through max.

Hardware Generation of Mipmaps

If you know beforehand that you want all mip levels loaded, you can also use OpenGL hardware acceleration to quickly generate all the necessary mip levels. You do so by setting the texture parameter GL_GENERATE_MIPMAP to GL_TRUE:

glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);

When this parameter is set, all calls to glTexImage or glTexSubImage that update the base texture map (mip level 0) automatically update all the lower mip levels. By making use of the graphics hardware, this feature is substantially faster than using gluBuildMipmaps. However, you should be aware that this feature was originally an extension and was promoted to the OpenGL core API only as of version 1.4.

LOD BIAS

When mipmapping is enabled, OpenGL uses a formula to determine which mip level should be selected based on the size of the mipmap levels and the onscreen area the geometry occupies. OpenGL does its best to make a close match between the mipmap level chosen and the texture's representation onscreen. You can tell OpenGL to move its selection criteria back (lean toward larger mip levels) or forward (lean toward smaller mip levels). This can have the effect of increasing performance (using smaller mip levels) or increasing the sharpness of texture-mapped objects (using larger mip levels). This bias one way or the other is selected with the texture environment parameter GL_TEXTURE_LOD_BIAS, as shown here:

glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, -1.5);

In this example, the texture level of detail is shifted slightly toward using higher levels of detail (smaller level parameters), resulting in sharper looking textures, at the expense of slightly more texture processing overhead.

Texture Objects

So far, you have seen how to load a texture and set texture parameters to affect how texture maps are applied to geometry. The texture image and parameters set with glTexParameter comprise the texture state. Loading and maintaining the texture state occupies a considerable portion of many texture-heavy OpenGL applications (such as games in particular).

Especially time consuming are function calls such as glTexImage, glTexSubImage, and gluBuildMipmaps. These functions move a large amount of memory around and possibly need to reformat the data to match some internal representation. Switching between textures or reloading a different texture image would ordinarily be a costly operation.

Texture objects allow you to load up more than one texture state at a time, including texture images, and switch between them very quickly. The texture state is maintained by the currently bound texture object, which is identified by an unsigned integer. You allocate a number of texture objects with the following function:

void glGenTextures(GLsizei n, GLuint *textures);

With this function, you specify the number of texture objects and a pointer to an array of unsigned integers that will be populated with the texture object identifiers. You can think of them as handles to different available texture states. To “bind” to one of these states, you call the following function:

void glBindTexture(GLenum target, GLuint texture);

The target parameter needs to specify either GL_TEXTURE_1D, GL_TEXTURE_2D, or GL_TEXTURE_3D, and texture is the specific texture object to bind to. Hereafter, all texture loads and texture parameter settings affect only the currently bound texture object. To delete texture objects, you call the following function:

void glDeleteTextures(GLsizei n, GLuint *textures);

The arguments here have the same meaning as for glGenTextures. You do not need to generate and delete all your texture objects at the same time. Multiple calls to glGenTextures have very little overhead. Calling glDeleteTextures multiple times may incur some delay, but only because you are deallocating possibly large amounts of texture memory.

You can test texture object names (or handles) to see whether they are valid by using the following function:

GLboolean glIsTexture(GLuint texture);

This function returns GL_TRUE if the integer is a previously allocated texture object name or GL_FALSE if not.

Managing Multiple Textures

Generally, texture objects are used to load up several textures at program initialization and switch between them quickly during rendering. These texture objects are then deleted when the program shuts down. The TUNNEL sample program loads three textures at startup and then switches between them to render a tunnel. The tunnel has a brick wall pattern with different materials on the floor and ceiling. The output from TUNNEL is shown in Figure 8.11.

A tunnel rendered with three different textures.

Figure 8.11. A tunnel rendered with three different textures.

The TUNNEL sample program also shows off mipmapping”and the different mipmapped texture filtering modes. Pressing the up- and down-arrow keys moves the point of view back and forth in the tunnel, and the context menu (right-click menu) allows you to switch among six different filtering modes to see how they affect the rendered image. The complete source code is provided in Listing 8.3.

Example 8.3. Source Code for the TUNNEL Sample Program

// Tunnel.c
// Demonstrates mipmapping"and using texture objects
// OpenGL SuperBible
// Richard S. Wright Jr.
#include "../../Common/OpenGLSB.h"  // System and OpenGL Stuff
#include "../../Common/GLTools.h"   // GLTools

// Rotation amounts
static GLfloat zPos = -60.0f;

// Texture objects
#define TEXTURE_BRICK   0
#define TEXTURE_FLOOR  1
#define TEXTURE_CEILING 2
#define TEXTURE_COUNT   3
GLuint  textures[TEXTURE_COUNT];
const char *szTextureFiles[TEXTURE_COUNT] =
                                 { "brick.tga", "floor.tga", "ceiling.tga" };



//////////////////////////////////////////////////////////////////////////////
// Change texture filter for each texture object
void ProcessMenu(int value)
    {
    GLint iLoop;

    for(iLoop = 0; iLoop < TEXTURE_COUNT; iLoop++)
        {
        glBindTexture(GL_TEXTURE_2D, textures[iLoop]);

        switch(value)
            {
            case 0:
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
                                                                GL_NEAREST);
                break;

            case 1:
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
                                                                 GL_LINEAR);
                break;

            case 2:
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
                                                 GL_NEAREST_MIPMAP_NEAREST);
                break;

            case 3:
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
                                                  GL_NEAREST_MIPMAP_LINEAR);
                break;

            case 4:
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
                                                  GL_LINEAR_MIPMAP_NEAREST);
                break;

            case 5:
            default:
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
                                                   GL_LINEAR_MIPMAP_LINEAR);
                break;
            }
        }

    // Trigger Redraw
    glutPostRedisplay();
    }


//////////////////////////////////////////////////////////////////
// This function does any needed initialization on the rendering
// context.  Here it sets up and initializes the texture objects.
void SetupRC()
    {
    GLubyte *pBytes;
    GLint iWidth, iHeight, iComponents;
    GLenum eFormat;
    GLint iLoop;

    // Black background
    glClearColor(0.0f, 0.0f, 0.0f,1.0f);

    // Textures applied as decals, no lighting or coloring effects
    glEnable(GL_TEXTURE_2D);
    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);

    // Load textures
    glGenTextures(TEXTURE_COUNT, textures);
    for(iLoop = 0; iLoop < TEXTURE_COUNT; iLoop++)
        {
        // Bind to next texture object
        glBindTexture(GL_TEXTURE_2D, textures[iLoop]);

        // Load texture, set filter and wrap modes
        pBytes = gltLoadTGA(szTextureFiles[iLoop],&iWidth, &iHeight,
                              &iComponents, &eFormat);
        gluBuild2DMipmaps(GL_TEXTURE_2D, iComponents, iWidth, iHeight, eFormat,
                              GL_UNSIGNED_BYTE, pBytes);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
                              GL_LINEAR_MIPMAP_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

        // Don't need original texture data any more
        free(pBytes);
        }
    }

///////////////////////////////////////////////////
// Shutdown the rendering context. Just deletes the
// texture objects
void ShutdownRC(void)
    {
    glDeleteTextures(TEXTURE_COUNT, textures);
    }


///////////////////////////////////////////////////
// Respond to arrow keys, move the viewpoint back
// and forth
void SpecialKeys(int key, int x, int y)
    {
    if(key == GLUT_KEY_UP)
        zPos += 1.0f;

    if(key == GLUT_KEY_DOWN)
        zPos -= 1.0f;

    // Refresh the Window
    glutPostRedisplay();
    }

/////////////////////////////////////////////////////////////////////
// Change viewing volume and viewport.  Called when window is resized
void ChangeSize(int w, int h)
    {
    GLfloat fAspect;

    // Prevent a divide by zero
    if(h == 0)
        h = 1;

    // Set Viewport to window dimensions
    glViewport(0, 0, w, h);

    fAspect = (GLfloat)w/(GLfloat)h;

    // Reset coordinate system
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    // Produce the perspective projection
    gluPerspective(90.0f,fAspect,1,120);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    }

///////////////////////////////////////////////////////
// Called to draw scene
void RenderScene(void)
    {
    GLfloat z;

    // Clear the window with current clearing color
    glClear(GL_COLOR_BUFFER_BIT);

    // Save the matrix state and do the rotations
    glPushMatrix();
        // Move object back and do in place rotation
        glTranslatef(0.0f, 0.0f, zPos);

       // Floor
        for(z = 60.0f; z >= 0.0f; z -= 10)
        {
        glBindTexture(GL_TEXTURE_2D, textures[TEXTURE_FLOOR]);
        glBegin(GL_QUADS);
            glTexCoord2f(0.0f, 0.0f);
            glVertex3f(-10.0f, -10.0f, z);

            glTexCoord2f(1.0f, 0.0f);
            glVertex3f(10.0f, -10.0f, z);

            glTexCoord2f(1.0f, 1.0f);
            glVertex3f(10.0f, -10.0f, z - 10.0f);

            glTexCoord2f(0.0f, 1.0f);
            glVertex3f(-10.0f, -10.0f, z - 10.0f);
        glEnd();

        // Ceiling
        glBindTexture(GL_TEXTURE_2D, textures[TEXTURE_CEILING]);
        glBegin(GL_QUADS);
            glTexCoord2f(0.0f, 1.0f);
            glVertex3f(-10.0f, 10.0f, z - 10.0f);

            glTexCoord2f(1.0f, 1.0f);
            glVertex3f(10.0f, 10.0f, z - 10.0f);

            glTexCoord2f(1.0f, 0.0f);
            glVertex3f(10.0f, 10.0f, z);

            glTexCoord2f(0.0f, 0.0f);
            glVertex3f(-10.0f, 10.0f, z);
        glEnd();


        // Left Wall
        glBindTexture(GL_TEXTURE_2D, textures[TEXTURE_BRICK]);
        glBegin(GL_QUADS);
            glTexCoord2f(0.0f, 0.0f);
            glVertex3f(-10.0f, -10.0f, z);

            glTexCoord2f(1.0f, 0.0f);
            glVertex3f(-10.0f, -10.0f, z - 10.0f);

            glTexCoord2f(1.0f, 1.0f);
            glVertex3f(-10.0f, 10.0f, z - 10.0f);

            glTexCoord2f(0.0f, 1.0f);
            glVertex3f(-10.0f, 10.0f, z);
        glEnd();

        // Right Wall
        glBegin(GL_QUADS);
            glTexCoord2f(0.0f, 1.0f);
            glVertex3f(10.0f, 10.0f, z);

            glTexCoord2f(1.0f, 1.0f);
            glVertex3f(10.0f, 10.0f, z - 10.0f);

            glTexCoord2f(1.0f, 0.0f);
            glVertex3f(10.0f, -10.0f, z - 10.0f);

            glTexCoord2f(0.0f, 0.0f);
            glVertex3f(10.0f, -10.0f, z);
        glEnd();
        }

    // Restore the matrix state
    glPopMatrix();

    // Buffer swap
    glutSwapBuffers();
    }


//////////////////////////////////////////////////////
// Program entry point
int main(int argc, char *argv[])
    {
    // Standard initialization stuff
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
    glutInitWindowSize(800, 600);
    glutCreateWindow("Tunnel");
    glutReshapeFunc(ChangeSize);
    glutSpecialFunc(SpecialKeys);
    glutDisplayFunc(RenderScene);

    // Add menu entries to change filter
    glutCreateMenu(ProcessMenu);
    glutAddMenuEntry("GL_NEAREST",0);
    glutAddMenuEntry("GL_LINEAR",1);
    glutAddMenuEntry("GL_NEAREST_MIPMAP_NEAREST",2);
    glutAddMenuEntry("GL_NEAREST_MIPMAP_LINEAR", 3);
    glutAddMenuEntry("GL_LINEAR_MIPMAP_NEAREST", 4);
    glutAddMenuEntry("GL_LINEAR_MIPMAP_LINEAR", 5);
    glutAttachMenu(GLUT_RIGHT_BUTTON);

    // Startup, loop, shutdown
    SetupRC();
    glutMainLoop();
    ShutdownRC();

    return 0;
    }

In this example, you first create identifiers for the three texture objects. The array textures will contain three integers, which will be addressed by using the macros TEXTURE_BRICK, TEXTURE_FLOOR, and TEXTURE_CEILING. For added flexibility, you also create a macro that defines the maximum number of textures that will be loaded and an array of character strings containing the names of the texture map files:

// Texture objects
#define TEXTURE_BRICK   0
#define TEXTURE_FLOOR  1
#define TEXTURE_CEILING 2
#define TEXTURE_COUNT   3
GLuint  textures[TEXTURE_COUNT];
const char *szTextureFiles[TEXTURE_COUNT] =
                                 { "brick.tga", "floor.tga", "ceiling.tga" };

The texture objects are allocated in the SetupRC function:

glGenTextures(TEXTURE_COUNT, textures);

Then a simple loop binds to each texture object in turn and loads its texture state with the texture image and texturing parameters:

for(iLoop = 0; iLoop < TEXTURE_COUNT; iLoop++)
    {
    // Bind to next texture object
    glBindTexture(GL_TEXTURE_2D, textures[iLoop]);

    // Load texture, set filter and wrap modes
    pBytes = gltLoadTGA(szTextureFiles[iLoop],&iWidth, &iHeight,
                              &iComponents, &eFormat);
    gluBuild2DMipmaps(GL_TEXTURE_2D, iComponents, iWidth, iHeight, eFormat,
                              GL_UNSIGNED_BYTE, pBytes);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
                              GL_LINEAR_MIPMAP_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    // Don't need original texture data any more
    free(pBytes);
    }

With each of the three texture objects initialized, you can easily switch between them during rendering to change textures:

glBindTexture(GL_TEXTURE_2D, textures[TEXTURE_FLOOR]);
     glBegin(GL_QUADS);
        glTexCoord2f(0.0f, 0.0f);
        glVertex3f(-10.0f, -10.0f, z);

        glTexCoord2f(1.0f, 0.0f);
        glVertex3f(10.0f, -10.0f, z);

        ...
        ...

Finally, when the program is terminated, you only need to delete the texture objects for the final cleanup:

///////////////////////////////////////////////////
// Shutdown the rendering context. Just deletes the
// texture objects
void ShutdownRC(void)
    {
    glDeleteTextures(TEXTURE_COUNT, textures);
    }

Also, note that when the mipmapped texture filter is set in the TUNNEL sample program, it is selected only for the minification filter:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);

This is typically the case because after OpenGL selects the largest available mip level, no larger levels are available to select between. Essentially, this is to say that once a certain threshold is passed, the largest available texture image is used and there are no additional mipmap levels to choose from.

Resident Textures

Most OpenGL implementations support a limited amount of high-performance texture memory. Textures located in this memory are accessed very quickly, and performance is high. Initially, any loaded texture is stored in this memory; however, only a limited amount of memory is typically available, and at some point textures may need to be stored in slower memory. As is often the case, this slower memory may even be located outside the OpenGL hardware (such as in a PC's system memory as opposed to being stored on the graphics card or in AGP memory).

To optimize rendering performance, OpenGL automatically moves frequently accessed textures into this high-performance memory. Textures in this high-performance memory are called resident textures. To determine whether a bound texture is resident, you can call glGetTexParameter and find the value associated with GL_TEXTURE_RESIDENT. Testing a group of textures to see whether they are resident may be more useful, and you can perform this test using the following function:

GLboolean glAreTexturesResident(GLsizei n, const GLuint *textures,
                                                    GLboolean *residences);

This function takes the number of texture objects to check, an array of the texture object names, and finally an array of Boolean flags set to GL_TRUE or GL_FALSE to indicate the status of each texture object. If all the textures are resident, the array is left unchanged, and the function returns GL_TRUE. This feature is meant to save the time of having to check through an entire array to see whether all the textures are resident.

Texture Priorities

By default, most OpenGL implementations use a Most Frequently Used (MFU) algorithm to decide which textures can stay resident. However, if several smaller textures are used only slightly more frequently than, say, a much larger texture, texturing performance can suffer considerably. You can provide hints to whatever mechanism an implementation uses to decide texture residency by setting each texture's priority with this function:

void glPrioritizeTextures(GLsizei n, const GLuint *textures,
                                                  const GLclampf *priorities);

This function takes an array of texture object names and a corresponding array of texture object priorities that are clamped between 0 and 1.0. A low priority tells the implementation that this texture object should be left out of resident memory whenever space becomes tight. A higher priority (such as 1.0) tells the implementation that you want that texture object to remain resident if possible, even if the texture seems to be used infrequently.

Summary

In this chapter, we extended the simple image loading and display methods from the preceding chapter to applying images as texture maps to real three-dimensional geometry. You learned how to load a texture map and use texture coordinates to map the image to the vertices of geometry. You also learned the different ways in which texture images can be filtered and blended with the geometry color values and how to use mipmaps to improve both performance and visual fidelity. Finally, we discussed how to manage multiple textures and switch between them quickly and easily, and how to tell OpenGL which textures should have priority if any high-performance (or local) texture memory is available.

Reference

glAreTexturesResident

Purpose:

Determine whether a set of texture objects is resident.

Include File:

<gl.h>

Syntax:

GLboolean glAreTexturesResident(GLsizei n, const 
ReferenceGLuint *textures,
                                                  
Reference  GLboolean *residences);

Description:

Many OpenGL implementations support a high-performance set of textures that are said to be resident. Resident textures are kept in local or fast memory accessible directly by the OpenGL hardware. Texturing with resident textures is substantially faster than using nonresident textures. This function allows you to test an array of texture object handles for residency. If all the texture object's queries are resident, the function returns GL_TRUE.

Parameters:

n

GLsizeiThe size of the array of texture objects.

textures

GLuint*The array containing texture object identifiers to be queried.

residences

GLboolean*The array to be populated with corresponding flags (GL_TRUE or GL_FALSE) for each texture object. If all the texture objects specified in textures are resident, the array is not modified.

Returns:

None

See Also:

glGenTextures, glBindTexture, glDeleteTextures, glPrioritizeTextures

glBindTexture

Purpose:

Binds the current texture state to the named target.

Include File:

<gl.h>

Syntax:

void glBindTexture(GLenum target, GLuint texture);

Description:

This function enables you to create or switch to a named texture state. On first use, this function creates a new texture state identified by the texture name, which is an unsigned integer. Subsequent calls with the same texture identifier select that texture state and make it current.

Parameters:

target

GLenumThe texture target to bind to. It must be GL_TEXTURE_1D, GL_TEXTURE_2D, or GL_TEXTURE_3D.

texture

GLuintThe name or handle of the texture object.

Returns:

None.

See Also:

glGenTextures, glDeleteTextures, glAreTexturesResidient, glPrioritizeTextures, glIsTexture

glCopyTexImage

Purpose:

Copies pixels from the color buffer into a texture.

Include File:

<gl.h>

Variations:

void glCopyTexImage1D(GLenum target, GLint level, 
GLuint:GLenum internalFormat,
                                GLint x, GLint y, 
GLuint:GLsizei width, GLint border);

void glCopyTexImage2D(GLenum target, GLint level, 
GLuint:GLenum internalFormat,
                GLint x, GLint y, GLsizei width, 
GLuint:GLsizei height, GLint border);

Description:

These functions define a one- or two-dimensional texture image using data read directly from the color buffer. If the source of a texture map is to be the result of a rendering operation, be sure to call glFinish to ensure that OpenGL has completed the rendering operation before calling this function. Data is read from the color buffer specified by the glReadBuffer function.

Parameters:

target

GLenumThe texture target. It must be GL_TEXTURE_1D for glCopyTexImage1D and GL_TEXTURE_2D for glCopyTexImage2D.

level

GLintThe mipmap level to be loaded.

internal Format

GLenumThe internal format and resolution of the texture data. This must be one of the constants for texture formats acceptable by glTexImage, with the exception that you cannot use the values 1, 2, 3, or 4 for the number of color components.

x, y

GLintThe location in the color buffer to begin reading color data.

width, height

GLsizeiThe width and height (for glCopyTexImage2D only) of the color data rectangle to be read from the color buffer.

border

GLintThe width of the texture border. Only 1 or 0 is allowed.

Returns:

None.

See Also:

glTexImage, glCopyTexSubImage

glCopyTexSubImage

Purpose:

Replaces part of a texture map using data from the color buffer.

Include File:

<gl.h>

Variations:

void glCopyTexSubImage1D(GLenum target, GLint level,
                                  GLint xoffset,
                                  GLint x, GLint y,
                                  GLsizei width);
void glCopyTexSubImage2D(GLenum target, GLint level,
                                  GLint xoffset, 
GLint:GLint yoffset,
                                  GLint x, GLint y,
                                  GLsizei width, 
GLint:GLsizei height);

void glCopyTexSubImage3D(GLenum target, GLint level,
                                  GLint xoffset, 
GLint:GLint yoffset, Glint zoffset,
                                  GLint x, GLint y,
                                  GLsizei width, 
GLint:GLsizei height);

Description:

This function replaces part of an existing texture map with data read directly from the color buffer. If the source of a texture map is to be the result of a rendering operation, be sure to call glFinish to ensure that OpenGL has completed the rendering operation before calling this function. Data is read from the color buffer specified by the glReadBuffer function.

Parameters:

target

GLenumThe texture target. It must be GL_TEXTURE_1D for glCopyTexSubImage1D, GL_TEXTURE_2D for glCopyTexSubImage2D, and GL_TEXTURE_3D for glcopyTexSubImage3D.

level

GLintThe mipmap level being updated.

xoffset

GLintThe x offset into the texture map to begin replacing data.

yoffset

GLintThe y offset into the two- or three-dimensional texture map to begin replacing data.

zoffset

GLintThe z offset into the three-dimensional texture map to begin replacing data.

x, y

GLintThe x,y location in the color buffer to begin reading the texture data.

width, height

GLsizeiThe width and height (for two and three dimensions only) of the data to be read from the color buffer.

Returns:

None.

See Also:

glTexImage, glCopyTexImage, glTexSubImage

glDeleteTextures

Purpose:

Deletes a set of texture objects.

Include File:

<gl.h>

Syntax:

void glDeleteTextures(GLsizei n, const GLuint 
GLsizei:*textures);

Description:

This function deletes a set of texture objects. When a texture object is deleted, it is available to be redefined by a subsequent call to glBindTexture. Any memory used by the existing texture objects is released and available for other textures. Any invalid texture object names in the array are ignored.

Parameters:

n

GLsizeiThe number of texture objects to delete.

textures

GLuint*An array containing the list of texture objects to be deleted.

Returns:

None.

See Also:

glGenTextures, glBindTexture

glGenTextures

Purpose:

Generates a list of texture object names.

Include File:

<gl.h>

Syntax:

void glGenTextures(GLsizei n, GLuint *textures);

Description:

This function fills an array with the requested number of texture objects. Texture object names are unsigned integers, but there is no guarantee that the returned array will contain a continuous sequence of integer names. Texture object names returned by this function are always be unique, unless they have been previously deleted with glDeleteTextures.

Parameters:

n

GLsizeiThe number of texture object names to generate.

textures

GLuint*An array containing the list of newly generated texture object names.

Returns:

None.

See Also:

glDeleteTextures, glBindTexture, glIsTexture

glGetTexLevelParameter

Purpose:

Returns texture parameters for a specific mipmap level.

Include File:

<gl.h>

Variations:

void glGetTexLevelParameterfv(GLenum target, GLint
GLuint*: level, GLenum pname,
                                                  
GLuint*:            GLfloat *params);
void glGetTexLevelParameteriv(GLenum target, GLint
GLuint*: level, GLenum pname,
                                                  
GLuint*:              GLint *params);

Description:

This function enables you to query for the value of a number of different parameters that may be valid for a specific texture mipmap level. Table 8.5 lists the specific texture level parameters that may be queried. Returned results may be contained in one or more floating-point or integer values.

Parameters:

target

GLenumThe texture target being queried. It must be GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D, GL_PROXY_TEXTURE_1D, GL_PROXY_TEXTURE_2D, GL_PROXY_TEXTURE_3D, GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, or GL_TEXTURE_CUBE_MAP_NEGATIVE_Z.

level

GLintThe mipmap level being queried.

pname

GLenumA constant value from Table 8.5 that specifies the texture parameter being queried.

params

GLfloat* or GLint*The returned parameter value or values are stored here.

Returns:

None.

See Also:

glGetTexParameter, glTexParameter

Table 8.5. Texture-Level Parameter Query Constants

Constant

Description

GL_TEXTURE_WIDTH

The width of the texture image, including the texture border if defined

GL_TEXTURE_HEIGHT

The height of the texture image, including the texture border if defined

GL_TEXTURE_DEPTH

The depth of the texture image, including the texture border if defined

GL_TEXTURE_INTERNAL_FORMAT

The internal format of the texture image

GL_TEXTURE_BORDER

The width of the texture border

GL_TEXTURE_RED_SIZE

The resolution in bits of the red component of a texel

GL_TEXTURE_GREEN_SIZE

The resolution in bits of the green component of a texel

GL_TEXTURE_BLUE_SIZE

The resolution in bits of the blue component of a texel

GL_TEXTURE_ALPHA_SIZE

The resolution in bits of the alpha component of a texel

GL_TEXTURE_LUMINANCE_SIZE

The resolution in bits of the luminance of a texel

GL_TEXTURE_INTENSITY_SIZE

The resolution in bits of the intensity of a texel

GL_TEXTURE_COMPONENTS

The number of color components in the texture image

GL_TEXTURE_COMPRESSED_IMAGE_SIZE

The size in bytes of the compressed texture image (must have a compressed internal format)

glGetTexParameter

Purpose:

Queries for texture parameter values.

Include File:

<gl.h>

Variations:

void glGetTexParameterfv(GLenum target, GLenum 
Texture-Level Parameter Query Constantspname, GLfloat *params);
void glGetTexParameteriv(GLenum target, GLenum 
Texture-Level Parameter Query Constantspname, GLint *params);

Description:

This function enables you to query for the value of a number of different texture parameters. This function is frequently used with one of the proxy texture targets to see whether a texture can be loaded. Table 8.6 lists the specific texture parameters that may be queried. Returned results may be contained in one or more floating-point or integer values.

Parameters:

target

GLenumThe texture target being queried. It must be GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D, GL_PROXY_TEXTURE_1D, GL_PROXY_TEXTURE_2D, GL_PROXY_TEXTURE_3D, or GL_TEXTURE_CUBE_MAP.

pname

GLenumThe parameter value being queried. It may be any constant from Table 8.6.

params

GLfloat* or GLint*Address of variable or variables to receive the parameter value or values.

Returns:

None.

See Also:

glGetTexLevelParameter, glTexParameter

Table 8.6. Texture Parameter Query Constants

Constant

Description

GL_TEXTURE_MAG_FILTER

Returns the texture magnification filter value

GL_TEXTURE_MIN_FILTER

Returns the texture minification filter

GL_TEXTURE_MIN_LOD

Returns the minimum level of detail value

GL_TEXTURE_MAX_LOD

Returns the maximum level of detail value

GL_TEXTURE_BASE_LEVEL

Returns the base texture mipmap level

GL_TEXTURE_MAX_LEVEL

Returns the maximum mipmap array level

GL_TEXTURE_LOD_BIAS

Texture Level of Detail bias

GL_TEXTURE_WRAP_S

Returns the wrap mode in the s coordinate direction

GL_TEXTURE_WRAP_T

Returns the wrap mode in the t coordinate direction

GL_TEXTURE_WRAP_R

Returns the wrap mode in the r coordinate direction

GL_TEXTURE_BORDER_COLOR

Returns the texture border color

GL_TEXTURE_PRIORITY

Returns the current texture priority settings

GL_TEXTURE_RESIDENT

Returns GL_TRUE if the texture is resident, GL_FALSE otherwise

GL_DEPTH_TEXTURE_MODE

Returns the depth texture mode

GL_TEXTURE_COMPARE_MODE

Returns the texture comparison mode

GL_TEXTURE_COMPARE_FUNC

Returns the texture comparison function

GL_TEXTURE_GENERATE_MIPMAP

Returns GL_TRUE if automatic mipmap generation is enabled

glGetTexImage

Purpose:

Returns a texture image.

Include File:

<gl.h>

Syntax:

void glGetTexImage(GLenum target, GLint level, 
Texture Parameter Query ConstantsGLenum format,
                                               
Texture Parameter Query Constants GLenum type, void *pixels);

Description:

This function enables you to fill a data buffer with the data that comprises the current texture. This function performs the reverse operation of glTexImage, which loads a texture with a supplied data buffer.

Parameters:

target

GLenumThe texture target to be copied. It must be GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, or GL_TEXTURE_CUBE_MAP_NEGATIVE_Z.

level

GLintThe mipmap level to be read.

format

GLenumThe desired pixel format of the returned data. It may be GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA, GL_RGB, GL_RGBA, GL_LUMINANCE, GL_BGR, GL_BGRA, or GL_LUMINANCE_ALPHA.

type

GLenumThe pixel type for the returned data. It may be any pixel type listed in Table 8.3.

pixels

void*Pointer to a memory buffer to accept the texture image.

Returns:

None.

See Also:

glTexImage

glIsTexture

Purpose:

Determines whether a texture object name is valid.

Include File:

<gl.h>

Syntax:

GLboolean glIsTexture(GLuint texture);

Description:

This function enables you to determine whether a given integer value is a valid texture object name. A valid texture object is an integer name that is in use. This means that glBindTexture has been used to bind to this texture object name at least once, and it has not been subsequently deleted with glDeleteTextures.

Parameters:

texture

GLuintThe texture object in question.

Returns:

GL_TRUE if the texture object is a valid (in-use) texture object name; GL_FALSE otherwise.

See Also:

glGenTextures, glDeleteTextures, glBindTexture, glAreTexturesResidient, glPrioritizeTextures

glPrioritizeTextures

Purpose:

Sets priority of a texture object.

Include File:

<gl.h>

Syntax:

void glPrioritizeTextures(GLsizei n, Gluint *textures,
                                             
GLuint: const GLclampf *priorities);

Description:

This function assigns n priorities to the texture objects contained in the textures array. The array of priorities is specified in priorities. A texture priority is a clamped value between 0.0 and 1.0 that provides the implementation with a hint that the given texture should remain resident. Resident textures are textures that are stored in high performance or local memory. A texture priority of 1.0 signifies a strong hint to keep the texture resident, whereas 0.0 signifies that the texture may be swapped out if necessary.

Parameters:

n

GLsizeiThe number of texture object names contained in the textures array.

textures

GLuint*An array of texture object names. Each array element corresponds to a priority to be set in the priorities array.

priorities

const GLclampf*An array of clamped floating-point values that specify a texture object's priority. The array element corresponds to a particular texture object name in the same location in the textures array.

Returns:

None.

See Also:

glAreTexturesResident, glGenTextures, glBindTexture, glDeleteTexture, glIsTexture

glTexCoord

Purpose:

Specifies the current texture image coordinate for textured polygon rendering.

Include File:

<gl.h>

Variations:

void glTexCoord1f(GLfloat s);
void glTexCoord1fv(GLfloat *v);
void glTexCoord1d(GLdouble s);
void glTexCoord1dv(GLdouble *v);
void glTexCoord1i(GLint s);
void glTexCoord1iv(GLint *v);
void glTexCoord1s(GLshort s);
void glTexCoord1sv(GLfloat *v);
void glTexCoord2f(GLfloat s, GLfloat t);
void glTexCoord2fv(GLfloat *v);
void glTexCoord2d(GLdouble s, GLdouble t);
void glTexCoord2dv(GLdouble *v);
void glTexCoord2i(GLint s, GLint t);
void glTexCoord2iv(GLint *v);
void glTexCoord2s(GLshort s, GLshort t);
void glTexCoord2sv(GLfloat *v);
void glTexCoord3f(GLfloat s, GLfloat t, GLfloat r);
void glTexCoord3fv(GLfloat *v);
void glTexCoord3d(GLdouble s, GLdouble t, GLdouble r);
void glTexCoord3dv(GLdouble *v);
void glTexCoord3i(GLint s, GLint t, GLint r);
void glTexCoord3iv(GLint *v);
void glTexCoord3s(GLshort s, GLshort t, GLshort r);
void glTexCoord3sv(GLfloat *v);
void glTexCoord4f(GLfloat s, GLfloat t, GLfloat r,
const GLclampf*: GLfloat q);
void glTexCoord4fv(GLfloat *v);
void glTexCoord4d(GLdouble s, GLdouble t, GLdouble
const GLclampf*: r, GLdouble q);
void glTexCoord4dv(GLdouble *v);
void glTexCoord4i(GLint s, GLint t, GLint r, Glint q);
void glTexCoord4iv(GLint *v);
void glTexCoord4s(GLshort s, GLshort t, GLshort r,
const GLclampf*: GLshort q);
void glTexCoord4sv(GLfloat *v);

Description:

These functions set the current texture image coordinate in one to four dimensions. Texture coordinates can be updated anytime between glBegin and glEnd, and correspond to the following glVertex call. The texture q coordinate is used to scale the s, t, and r coordinate values and by default is 1.0. You can perform any valid matrix operation on texture coordinates by specifying GL_TEXTURE as the target of glMatrixMode.

Parameters:

s

GLdouble or GLfloat or GLint or GLshortThe horizontal texture image coordinate.

t

GLdouble or GLfloat or GLint or GLshortThe vertical texture image coordinate.

r

GLdouble or GLfloat or GLint or GLshortThe texture image depth coordinate.

q

GLdouble or GLfloat or GLint or GLshortThe texture image scaling value coordinate.

v

GLdouble* or GLfloat* or GLint* or GLshort*An array of values that contain the one, two, three, or four values needed to specify the texture coordinate.

Returns:

None.

See Also:

glTexGen, glTexImage, glTexParameter

glTexEnv

Purpose:

Sets the texture environment parameters.

Include File:

<gl.h>

Variations:

void glTexEnvf(GLenum target, GLenum pname, 
GLdouble* or GLfloat* or GLint* or GLshort*:GLfloat param);
void glTexEnvfv(GLenum target, GLenum pname, 
GLdouble* or GLfloat* or GLint* or GLshort*:GLfloat *param);
void glTexEnvi(GLenum target, GLenum pname, GLint 
GLdouble* or GLfloat* or GLint* or GLshort*:param);
void glTexEnviv(GLenum target, GLenum pname, GLint
GLdouble* or GLfloat* or GLint* or GLshort*: *param);

Description:

These functions set texture mapping environment parameters. The texture environment is set per texture unit and exists outside the state bound by glBindTexture. Thus, all texture objects that can be bound to an active texture unit are influenced by the texture environment.

Parameters:

target

GLenumThe texture environment to define. It must be GL_TEXTURE_ENV or GL_TEXTURE_FILTER_CONTROL.

pname

GLenumThe parameter name to define.

When the target is GL_TEXTURE_FILTER CONTROL, the parameter name must be GL_TEXTURE_LOD_BIAS, and the parameter is the value that biases the mipmap level of the detail selection.

When the target is GL_TEXTURE_ENV, the parameter name may be GL_TEXTURE_ENV_MODE, GL_TEXTURE_ENV_COLOR, GL_COMBINE_RGB, or GL_COMBINE_ALPHA.

 

When the parameter name is GL_TEXTURE_ENV_COLOR, the parameter points to an array containing the color values of the texture environment color.

 

When the parameter name is GL_TEXTURE_ENV_MODE, the valid parameters are GL_REPLACE, GL_DECAL, GL_MODULATE, GL_BLEND, GL_ADD, or GL_COMBINE. These environment modes are described in Table 8.7.

param

The parameter value. It must be one of the values above (GL_REPLACE, GL_DECAL, GL_MODULATE, GL_BLEND, GL_ADD, or GL_COMBINE), or for GL_TEXTURE_ENV_COLOR, an array containing the RGBA color components of the texture environment color.

Returns:

None.

See Also:

glTexParameter

Table 8.7. Texture Environment Modes

Constant

Description

GL_DECAL

Texel values are applied to geometry fragment values. If blending is enabled and the texture contains an alpha channel, the geometry blends through the texture according to the current blend function.

GL_REPLACE

Texel values replace geometry fragment values. If blending is enabled and the texture contains an alpha channel, the texture's alpha values are used to replace the geometry fragment colors in the color buffer.

GL_MODULATE

Texel color values are multiplied by the geometry fragment color values.

GL_ADD

Texel color values are added to the geometry color values.

GL_BLEND

Texel color values are multiplied by the texture environment color.

GL_COMBINE

Texel color values are combined with a second texture unit according to the texture combine function (see the next chapter).

glTexImage

Purpose:

Defines a one-, two-, or three-dimensional texture image.

Include File:

<gl.h>

Variations:

void glTexImage1D(GLenum target, GLint level, 
Texture Environment ModesGLint internalformat,
               GLsizei width, GLint border,
               GLenum format, GLenum type, void 
Texture Environment Modes*data);

void glTexImage2D(GLenum target, GLint level, 
Texture Environment ModesGLint internalformat,
               GLsizei width, GLsizei height, 
Texture Environment ModesGLint border,
               GLenum format, GLenum type, void 
Texture Environment Modes*data);
void glTexImage3D(GLenum target, GLint level, 
Texture Environment ModesGLint internalformat,
               GLsizei width, GLsizei height, 
Texture Environment ModesGLsizei depth, GLint border,
               GLenum format, GLenum type, void 
Texture Environment Modes*data);

Description:

This function defines a one-, two-, or three-dimensional texture image. The image data is subject to modes defined with glPixelMap, glPixelStore, and glPixelTransfer.

Parameters:

target

GLenumThe texture target being specified. Must be GL_TEXTURE_1D or GL_PROXY_TEXTURE_1D for glTexImage1D, GL_TEXTURE_2D or GL_PROXY_TEXTURE_2D for glTexImage3D, GL_TEXTURE_3D or GL_TEXTURE_PROXY_3D for glTexImage3D. For 2D cube maps only, it may also be GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_CUBE_MAP_POSITIVE_Y, GL_CUBE_MAP_NEGATIVE_Y, GL_CUBE_MAP_POSITIVE_Z, or GL_CUBE_MAP_NEGATIVE_Z.

level

GLintThe level of detail. Usually, 0 unless mipmapping”is used.

internalFormat

GLintThe internal format of the image data. It may contain the numbers 1–4 to specify the number of color components, or one of the following constants: GL_ALPHA, GL_ALPHA4, GL_ALPHA8, GL_ALPHA12, GL_ALPHA16, GL_LUMINANCE, GL_LUMINANCE4, GL_LUMINANCE8, GL_LUMINANCE12, GL_LUMINANCE16, GL_LUMINANCE_ALPHA, GL_LUMINANCE4_ALPHA4, GL_LUMINANCE6_ALPHA2, GL_LUMINANCE8_ALPHA8, GL_LUMINANCE12_ALPHA4, GL_LUMINANCE12_ALPHA12, GL_LUMINANCE16_ALPHA16, GL_INTENSITY, GL_INTENSITY4, GL_INTENSITY8, GL_INTENSTIY12, GL_INTENSITY16, GL_RGB, GL_R3_G3_B2, GL_RGB4, GL_RGB5, GL_RGB8, GL_RGB10, GL_RGB12, GL_RGB16, GL_RGBA, GL_RGBA2, GL_RGBA4, GL_RGB5_A1, GL_RGBA8, GL_RGB10_A2, GL_RGBA12, GL_RGBA16.

width

GLsizeiThe width of the one-, two-, or three-dimensional texture image. This must be a power of 2 but may include a border.

height

GLsizeiThe height of the two- or three-dimensional texture image. This must be a power of 2 but may include a border.

depth

GLsizeiThe depth of a three-dimensional texture image. This must be a power of 2 but may include a border.

border

GLintThe width of the border. All implementations must support 0, 1, and 2 texel borders.

format

GLenumThe format of the pixel data. Any texel format type from Table 8.2 is valid.

type

GLenumThe data type of each texel value. Any data type from Table 8.3 is valid.

pixels

GLvoid *The pixel data.

Returns:

None.

See Also:

glTexSubImage, glCopyTexImage, glCopyTexSubImage

glTexParameter

Purpose:

Sets texture mapping parameters.

Include File:

<gl.h>

Variations:

void glTexParameterf(GLenum target, GLenum pname, 
GLvoid *:GLfloat param);
void glTexParameterfv(GLenum target, GLenum pname,
GLvoid *: GLfloat *param);
void glTexParameteri(GLenum target, GLenum pname, 
GLvoid *:GLint param);
void glTexParameteriv(GLenum target, GLenum pname,
GLvoid *: GLint *param);

Description:

This function sets several texture mapping parameters. These parameters are bound to the current texture state that can be made current with glBindTexture.

Parameters:

target

GLenumThe texture target for which this parameter applies. Must be one of GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D, or GL_TEXTURE_CUBE_MAP.

pname

GLenumThe texturing parameter to set. Valid names are as follows:

GL_TEXTURE_MIN_FILTERSpecifies the texture image minification (reduction) method or filter. Any texture filter from Table 8.4 may be used.

GL_TEXTURE_MAX_FILTERSpecifies the texture image magnification (enlargement) method or filter. Any texture filter from Table 8.4 may be used.

GL_TEXTURE_MAX_LODSpecifies the maximum texture LOD to be used for mipmapping.

GL_TEXTURE_MIN_LODSpecifies the minimum texture LOD to be used for mipmapping.

GL_TEXTURE_BASE_LEVELSpecifies the minimum texture LOD to be loaded.

GL_TEXTURE_MAX_LEVELSpecifies the maximum texture LOD to be loaded.

GL_TEXTURE_WRAP_SSpecifies handling of texture s coordinates outside the range of 0.0 to 1.0 (GL_CLAMP, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER, GL_REPEAT, GL_MIRRORED_REPEAT).

GL_TEXTURE_WRAP_TSpecifies handling of texture t coordinates outside the range of 0.0 to 1.0 (GL_CLAMP, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER, GL_REPEAT, GL_MIRRORED_REPEAT).

 

GL_TEXTURE_WRAP_RSpecifies handling of texture r coordinates outside the range of 0.0 to 1.0 (GL_CLAMP, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER, GL_REPEAT).

 

GL_BORDER_COLORSpecifies a border color for textures without borders.

 

GL_GENERATE_MIPMAPSpecifies whether mipmap LODs should be automatically built (GL_TRUE = yes).

 

GL_TEXTURE_PRIORITYSets the texture priority for this texture. It must be a clamped value in the range 0.0 to 1.0.

 

GL_DEPTH_TEXTURE_MODESets the depth texture mode (see Chapter 18).

 

GL_TEXTURE_COMPARE_MODESets the texture comparison mode (see Chapter 18).

 

GL_TEXTURE_COMPARE_FUNCSets the texture comparison function (see Chapter 18).

param

GLfloat or GLfloat* or GLint or GLint*Value of the parameter specified by pname.

Returns:

None.

See Also:

glTexEnv, glTexGen, glBindTexture

glTexSubImage

Purpose:

Replaces a portion of an existing texture map.

Include File:

<gl.h>

Variations:

void glTexSubImage1D(GLenum target, GLint level,
                                 GLint xOffset,
                                 GLsizei width,
                                 GLenum format, 
GLfloat or GLfloat* or GLint or GLint*:GLenum type, const GLvoid *data);

void glTexSubImage2D(GLenum target, GLint level,
                                 GLint xOffset, 
GLfloat or GLfloat* or GLint or GLint*:GLint yOffset,
                                 GLsizei width, 
GLfloat or GLfloat* or GLint or GLint*:GLsizei height,
                                 GLenum format, 
GLfloat or GLfloat* or GLint or GLint*:GLenum type, const GLvoid *data);

void glTexSubImage3D(GLenum target, GLint level,
                                 GLint xOffset, 
GLfloat or GLfloat* or GLint or GLint*:GLint yOffset, GLint zOffset,
                                 GLsizei width, 
GLfloat or GLfloat* or GLint or GLint*:GLsizei height, GLsizei depth,
                                 GLenum format, 
GLfloat or GLfloat* or GLint or GLint*:GLenum type, const GLvoid *data);

Description:

This function replaces a portion of an existing one-, two-, or three-dimensional texture map. Updating all or part of an existing texture map may be considerably faster than reloading a texture image with glTexImage. You cannot perform an initial texture load with this function; it is used only to update an existing texture.

Parameters:

target

GLenumThe texture target. Must be GL_TEXTURE_1D, GL_TEXTURE_2D, or GL_TEXTURE_3D.

level

GLintMipmap level to be updated.

xOffset

GLintOffset within the existing one-, two-, or three-dimensional texture in the x direction to begin the update.

yOffset

GLintOffset within the existing two- or three-dimensional texture in the y direction to begin the update.

zOffset

GLintOffset within the existing three-dimensional texture in the z direction to begin the update.

width

GLsizeiThe width of the one-, two-, or three-dimensional texture data being updated.

height

GLsizeiThe height of the two- or three-dimensional texture data being updated.

depth

GLsizeiThe depth of the three-dimensional texture data being updated.

format

GLenumAny valid texture format. See Table 8.2.

type

GLenumAny valid pixel data type. See Table 8.3.

data

const void*Pointer to the data that is being used to update the texture target.

Returns:

None.

See Also:

glTexImage, glCopyTexSubImage

gluBuildMipmapLevels

Purpose:

Automatically generates and updates a range of mipmap levels.

Include File:

<gl.h>

Variations:

int gluBuild1DMipmapLevels(GLenum target, GLint 
const void*:internalFormat,
                                      GLint width,
                                      GLenum
const void*: format, GLenum type, GLint level,
                                      GLint base, 
const void*:GLint max, const void *data);

int gluBuild2DMipmapLevels(GLenum target, GLint 
const void*:internalFormat,
                                      GLint width,
const void*: GLint height,
                                      GLenum
const void*: format, GLenum type, GLint level,
                                      GLint base, 
const void*:GLint max, const void *data);

int gluBuild3DMipmapLevels(GLenum target, Glint 
const void*:internalFormat,
                                      GLint width,
const void*: GLint height, GLint depth,
                                      GLenum
const void*: format, GLenum type, GLint level,
                                      GLint base, 
const void*:GLint max, const void *data);

Description:

This function uses gluScaleImage to automatically scale and load a series of mipmap levels based on an initial level provided. The advantage to using this function is that it allows only a selected range of mip levels to be updated.

Parameters:

target

GLenumThe texture target. Must be GL_TEXTURE_1D, GL_TEXTURE_2D, or GL_TEXTURE_3D.

internal Format

GLintAny valid texture internal format recognized by glTexImage.

width

GLintThe width of the one-, two-, or three-dimensional texture source.

height

GLintThe height of the two- or three-dimensional texture source.

depth

GLintThe depth of the three-dimensional texture source.

format

GLenumAny valid texel format. See Table 8.2.

type

GLenumAny valid texel data type. See Table 8.3.

level

GLintThe base mipmap level being specified by the data in data.

base

GLintThe starting mip level to begin mipmap generation.

max

GLintThe highest mip level (smallest image) to generate.

data

void*The supplied texture image data.

Returns:

None.

See Also:

gluBuildMipmaps

gluBuildMipmaps

Purpose:

Automatically creates and loads a set of complete mipmaps.

Include File:

<gl.h>

Variations:

int gluBuild1DMipmaps(GLenum target, GLint 
void*:internalFormat,
                                 GLint width,
                                 GLenum format, 
void*:GLenum type, const void *data);
int gluBuild2DMipmaps(GLenum target, GLint 
void*:internalFormat,
                                 GLint width, 
void*:GLint height,
                                 GLenum format, 
void*:GLenum type, const void *data);

int gluBuild3DMipmaps(GLenum target, GLint
void*: internalFormat,
                                 GLint width, 
void*:GLint height, GLint depth,
                                 GLenum format, 
void*:GLenum type, const void *data);

Description:

This function takes the texture data given for the base mipmapped texture level and automatically scales the image repeatedly and loads each mip level in turn. This work is done by the client CPU and not by the OpenGL implementation, and thus may be a time-consuming operation:

.

 

Parameters:

target

GLenumThe texture target. Must be GL_TEXTURE_1D, GL_TEXTURE_2D, or GL_TEXTURE_3D.

internalFormat

GLintAny valid texture internal format recognized by glTexImage.

width

GLintThe width of the one-, two-, or three-dimensional texture source.

height

GLintThe height of the two- or three-dimensional texture source.

depth

GLintThe depth of the three-dimensional texture source.

format

GLenumAny valid texel format. See Table 8.2.

type

GLenumAny valid texel data type. See Table 8.3.

data

void*The base mipmap level texture data.

Returns:

None:

.

 

See Also:

gluBuildMipmapLevels

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset