The OpenGL Texture Mapping
Survival Guide

Mike Hvidsten
MCS394 Spring 2004

  
A. To use basic texture mapping:

Step 1: Create a texture pattern (bitmap or procedural) and bind a name reference to it.  
       Note:  The same routine
                 glBindTexture(GL_TEXTURE_2D,  GLuint textureName);
                 is used to both create a new texture name and reference an
                 existing texture name.  When a name is initially bound, default
                 values are used for texture properties. Subsequent calls to glTexImage2D() and
                 glTexParameter*() store data in that texture object.

       Note: The actual texture is created with
                 glTexImage2D(GLenum target, GLint level, GLint internalFormat,
                        GLsizei width, GLsizei height, GLint border, GLenum format,
                        GLenum type, const GLvoid *textelArray)
;
                  There are a lot of possible parameters here. We will use a simple
                  texture map where
                                 target = GL_TEXTURE_2D
                                 level = 0
                                 internalFormat = GL_RGB   (stored OpenGL fomat of text data)
                                 width, height = dimensions of textel data  (powers of 2)
                                 border = 0   or 1  (whether texture has a border)
                                 format =  GL_RGB  or GL_RGBA
                                                (format of data read from textel file)
                                                (GL_RGB for *.bmp files and
                                                  GL_RGBA for *.rgb files)
                                 type = GL_UNSIGNED_BYTE  (single datum of textel file)
                                 texelArray = array of texel data
        Examples:
Case I: Use texture.c, texture.h to read in an rgb file (must have dimensions
    a power of 2)  This example defines a simple texture with filtering
    using the nearest neighbor.
#define TEX_ID 0

// in init()
unsigned int *image, *envImage;  
 int width, height, components;
// Attach a name to the texture for later use
glBindTexture(GL_TEXTURE_2D, TEX_ID);     
// Define how pixels are packed in arrays
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);  
image = read_texture("mandrill256.rgb", &width, &height, &components);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D,  0, components,  width,
         height,  0,  GL_RGBA,  GL_UNSIGNED_BYTE,  image);

NOTE: Make sure the last line has "RGBA" defined and not "RGB".
Case II: Use SDL.cpp. SDL.h, to read in a *.bmp file
     (again, must have dimensions a power of 2)
     This example defines a texture map with nearest neighbor filtering
     and clamped repetition of textures.
#define TEX_ID 1

// in init()
glBindTexture(GL_TEXTURE_2D, TEX_ID);     
// make one (empty) pixmap
RGBpixmap pix[1];     
// make pixmap from image
pix[0].readBMPFile("Mandrill.bmp");  
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
         pix[0].nCols, pix[0].nRows, 0, GL_RGB,
         GL_UNSIGNED_BYTE, pix[0].pixel);

NOTE : Make sure the second to the last line has "RGB"
   defined and not "RGBA"
Case III: Defining a mipmap sequence of textures
        We use the utility routine
      gluBuild2DMipmaps(
GLenum target, GLint internalFormat,
                        GLsizei width, GLsizei height, GLenum format,
                        GLenum type, const GLvoid *textelArray)
;
        The parameters have the same meaning as the
        parameters for glTexImage2D above.
       
             #define TEX_ID 2

            // in init()
            unsigned int *image, *envImage;  
            int width, height, components;
            glBindTexture(GL_TEXTURE_2D, TEX_ID);     
            glPixelStorei(GL_UNPACK_ALIGNMENT, 1);  
            image = read_texture("mandrill256.rgb", &width, &height,
                                                    &components);
            // Build all of the texture maps
           gluBuild2DMipmaps(GL_TEXTURE_2D, components, width, height,
                           GL_RGBA, GL_UNSIGNED_BYTE, image );


Step 2: Define texture filtering and wrapping parameters for the texture pattern
          (This can be done anywhere, usually in init() or when an object is displayed.)

                glTexParameteri(Glenum target, GLenum Param, TYPE Param_value);
                    (target = GL_TEXTURE2D)

                
Param
Possible Param_value
GL_TEXTURE_WRAP_S
GL_CLAMP, GL_CLAMP_TO_EDGE,
GL_CLAMP_TO_BORDER, GL_REPEAT,
GL_MIRRORED_REPEAT
GL_TEXTURE_WRAP_T
(same)
GL_TEXTURE_MAG_FILTER
GL_NEAREST, GL_LINEAR
GL_TEXTURE_MIN_FILTER
GL_NEAREST, GL_LINEAR,
GL_NEAREST_MIPMAP_NEAREST,
GL_NEAREST_MIPMAP_LINEAR,
GL_LINEAR_MIPMAP_NEAREST,
GL_LINEAR_MIPMAP_LINEAR,
Others (pg. 421 - Red Book)
See Chapter 9 - Red Book

     
Note: To get a feel for how these parameters affect a texture mapping of a
             scene, take a look at Nate Robbins Texture Demo Tutorial
            (linked off Project5 web page).

Step 3: Texture Map Shading:
         Define how colors at each vertex are shaded:
            glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,
                            TYPE value
);
        The parameter value = one of  (GL_DECAL, GL_REPLACE, GL_MODULATE,
                                                              GL_BLEND, GL_ADD, GL_COMBINE)
          For GL_DECAL, texture is placed on surface with no shading.
          For GL_MODULATE, texture color is adjusted by shading equation.
          These two are the most widely used.
          For a detailed explanation of the other types, see Chapter 9 of the Red Book,
           or experiment with Nate Robbins tutorial.
   
Step 4: Enable Texture Mapping:
glEnable(GL_TEXTURE_2D);

Step 5: Define Texture Coordinates: (Per Vertex of Polygon)
 (Look at checkerAlias.c for simple example)
           glTexCoord2f(GLfloat s, GLfloat t);

                     Note: If the coordinates are out of the range [0.0,1.0], the the texture
                            is repeated based on how you defined the wrapping parameter above.
                     Note: Texture Coordinates are defined vertex by vertex and always
                            precede the vertex they will be applied to.
                     Note: For some objects defined in terms of quadric surfaces
                           (sphere, cone, cylinder, disk) there are utility
                           routines to defined the texture coordinates:

// Create A Pointer To The Quadric Object
GLUquadricObj *quadratic=gluNewQuadric(); 
// Create Smooth Normals     
gluQuadricNormals(quadratic, GLU_SMOOTH);   
// Create Texture Coords
gluQuadricTexture(quadratic, GL_TRUE);               

B. Automatic Texture Generation:
This is a fairly advanced topic, but if you want to see the effects, run the
texShapes demo found on the Project5 web site.