CP2060 - Lecture 17 - Texture Mapping

 

Very often in 3D, it is desirable to use an image (perhaps a distinguishable image like a face or just some different colours arranged to make a 'texture') to "wrap around" the surface of an object. You will see this in 3D games, (e.g. Goldeneye for N64), where the bad guys look quite good from a distance, but when you get really close you notice their faces aren't modelled, they're just boxes with pictures of faces on them. This is quite acceptable, of course.

Hill - Fig 8.32

This example is a cylinder with a label mapped on to it - in front of a plane with an image of bricks mapped on to it. How much harder would it be to model this?

There are two kinds of textures used in 3D (for both OpenGL and programs like Inspire3D):

  • Image-based textures
  • Procedural textures

Images can be any regular picture from any source (although the size and format might be important depending on your use).

Procedural textures are images that are created from some form of procedure or mathematical function. Inspire3D's built in "ripples" and "fractal bumps" are good examples of these (covered in lecture 06).

The image of the dog above is an image map, with the ball on the right being a procedural texture.

Textures are created by a texture function - texture(t,s), the parameters of which are the x and y coordinates of the pixels in the image (or parameters for the function if it's procedural). t and s are always defined from 0 to 1, with 1 being the extremity of the image.

To get textures on to your surfaces in OpenGL, you use the glTexCoord2f(s,t) function along with each vertex in your face. This sets the position of the texture with respect to the face. Normally a quad polygon will have the four texture coordinate extremities mapped on to its vertices, but this can be set at will.

glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0); glVertex3f(1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0, 1.0); glVertex3f(-1.0f, 1.0f, -1.0f);
glTexCoord2f(1.0, 1.0); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0, 0.0); glVertex3f(1.0f, -1.0f, -1.0f);
glEnd();

The above code maps the current texture (see below) on to the polygon using the coordinates as defined.

OpenGL does not provide functionality for loading external images, but this has been implemented in the source code example files below.
Once the image has been loaded it needs to be associated with the 'current texture' so that it can be mapped on to a polygon.

glBindTexture(GL_TEXTURE_2D,textureName);
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,nCols,nRows,0, GL_RGB, GL_UNSIGNED_BYTE, pixel);

The first line binds the texture to a particular 'name' (integer) so that it can be referenced when needed. The next two set the parameters for how OpenGL should deal with the image when it needs to be resized up or down (as will almost always be the case, unless the number of pixels in the image are equal to the number in the polygon in both directions). The 'GL_NEAREST' property means to simply use the texel (texture element) that is nearest the centre of the pixel. The final line does the actual associating of the pixmap (in this case a 2D array of pixels called "pixel") to the current texture.

To tile the image over a surface, you can simply use s and t values of more than 1; e.g. a value of 2 in s and 3 in t will tile (perfectly) twice horizontally and three times vertically.
This also works for zooming in on an image - simply use values of less than 1.

You also need to enable texturing - glEnable(GL_TEXTURE_2D);

You can use any bitmap format for textures, provided you can write code to read it in to a 2D array (although textures can also be 1D and 3D). The code from Hill, chapter 8 reads 24 bit BMP files.
OpenGL specifies that texture map images must be 2^n pixels square (64x64, 256x256...). To use these square images to map onto non-square shapes, simply use the part of the image that you want by specifying the appropriate coordinates.

As well as using textures for image mapping, you can also use them for defining contours (bump mapping) and reflections (environment mapping) (as in Inspire3D).


Code

The source code example below was compiled from various parts of the text, mainly Figure 8.52, with the RGBpixmap.h file added to from the appendix3.cpp file. There are also some sample bmp files for use in this program.
Download all of the files and then open the workspace (.dsw):

There is also a sample program here taken from the Romka Graphics link (see links). This file works similarly to the above example, but with some differences. It loads TGA files instead of BMP, it has some interaction (a,z, mouse buttons), and it's implemented in C.

 

 

 Announcements

Lecture notes are provided as a guide of the content of lectures for pre-reading, revision and for students who cannot attend lectures. While almost every effort is made to make the online notes as complete as possible, there is always material discussed in lectures that is not in the notes.
You should not rely on these notes only!
If you miss a lecture and you do not understand something in the notes, you should consult (in this order) other students, the tutors, or the lecturer to try to work it out.

You are expected to read these lecture notes as well as attending lectures, as vital information is contained in both.

 

 Subject Coordinator: Lindsay {w} | {e}.

Last Update: October 2, 2001