Texture Mapping and Backface Culling

What you'll learn in this tutorial:

How can I load a texture image?

Texture mapping is a very powerful technique and is used in every 3d-game today. The first thing you need is an image with the texture data. To get realistic textures, you could take a photograph of grass, a brick wall and so on. Many tutorial writers define a two dimensional array in their programs and use it as texture.This is ok to see how texture mapping works, but it doesn't look good and is not used in any game. Instead, the textures are edited (or created) in a graphics program, saved and then loaded by the game. Here the hardware independence of OpenGL makes life a bit more difficult for us, because it cannot provide functions for loading a file – file management is different in every OS. But as mentioned in the introduction, there are helper functions. I'll explain loading a Windows bitmap by using the GLAux library, so you have to include "GL\glaux.h" and add glaux.lib to your project (at least in VC++).

Before loading, you tell OpenGL, that you want to used unpacked data and the for each of the components (r,g,b and perhaps a) 1 byte is used. This is done by

glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

Now you have to set four parameters: Two tell OpenGL what happens if a texture coordinate is not on the image and what shall be done, when the texture must be minificated or magnificated (Filtering paramters).

this is done by glTexParameteri(). The first argument is GL_TEXTURE_2D, the second is the variable to be changed. GL_TEXTURE_WRAP_S, GL_ TEXTUE_ WRAP_T are used to specify what happens if the texture coordinates are out of the range of the image in x or y, GL_TEXTURE_MAG_FILTER and GL_TEXTURE_MIN_FILTER tell OpenGL how to filter when the size of the texture gets bigger or smaller on the screen (that is nearly always). For the wrap paramters you should use GL_REPEAT (the other possibility would be GL_CLAMP). For the filtering parameters it gets a bit more difficult: For the GL_TEXTURE_MAG_FILTER you can decide between GL_NEAREST and GL_LINEAR. The first one is faster and doesn't look as good as the second one. For GL_TEXTURE_MIN_FILTER there are far more possibilites: GL_NEAREST, GL_LINEAR, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR. If you are using mipmaps you should use one with MIPMAP. They are sorted here by their rendering speed. Just check them out!

Now let's go to loading: As with display lists, you create a number for the texture:   glGenTextures(1, &Num);  Now you have to set this texture "active". This is done by glBindTexture(GL_TEXTURE_2D, Num); As you see, there are not only 2d-textures possible with OpenGl, but it is the mostly used type. We could write an own function for loading a windows bitmap, but there is an aux-function, that does the same. First you must declare

_AUX_RGBImageRec *Image;

then you can call

Image = auxDIBImageLoadA( (const char*) filename );

But OpenGL doesn't have the data yet. You still have to pass a pointer to it. This could be done by some gl*-calls, but there is a very comfortable glu*-routine:  It could look like that:

gluBuild2DMipmaps(    GL_TEXTURE_2D,
                             3,
                             Image->sizeX,
                             Image->sizeY,
                             GL_RGB,
                             GL_UNSIGNED_BYTE,
                             Image->data);

This call would create three mipmaps itsself, you don't have to store mipmaps in files.

Finally you define the "texture environment": glTexEnvf().

With this command you can specify, if you want to take the color from the texture and write it to the color buffer or if you want to "mix " it with the current color or the fragment that is already on the screen. To replace to fragment, you call

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

Other possible values would GL_DECAL, GL_BLEND and GL_MODULATE.

How can I use a texture image?

First of all, you have to turn on texture mapping. To do so you change the state variable for texture mapping by calling

glEnable(GL_TEXTURE_2D);

The next step is to set the desired texture active. For this you call glBindTexture(), you know this command already.

Then you only have to make a call to glTexCoord2f() before each glVertex*(). Note that you don't pass the coordinates in pixels. 0.0 for x is left, 1.0 is right. If a coordinate is not in this range, the tetxure is repeated (at least, when the GL_TEXTURE_WRAP_* parameter is set to GL_REPEAT).

A very useful thing is to write a class to handle a texture. I have done this, here you can see the result.

How can I use Backface Culling?

Backface culling (BfC) means, that the polygons that "look" away from the view are not rendered. This is normally very useful, because about half the polygons fall away. Sometime it can nearly double your framerate! But you must be careful: It only works, when your objects are ok. There mustn't be polygons which are visible from both sides (or you have to turn BfC off for these)!

We already dealed with front and back sides (see Depth testing and Lighting). After specifying what "front face" means (cw,ccw), you need only two calls to use BfC:

glCullFace(GL_BACK);

glEnable(GL_CULL_FACE);

This is all, only your models must have correctly oriented polygons!

 

Click here to see my code for this tutorial.

 

Back

**************************************************************************

Any comments? Conact me!

philipp.crocoll@web.de

www.codecolony.de