Textur
Børre Stenseth
OpenGL>Textures

Textures

What
self
Textures. Introduction and principles

OpenGL has tools to put textures on surfaces and to show bitmaps without connecting them to a specific surface. We will look at the basic functionality of textures. Whenever we work with bitmaps for one purpose or an other we will always need some tools to load and modify them. Much of this job can be done in editors, but you may need some imaging library. Maybe Dev IL [1] may be of use.

It is fairly easy to imaging a bitmap put on a surface like some kind of blanket. We must however be able to handle some situations.

We must be able to:

  • extract parts of a bitmap and put it on a surface.
  • stretch or shrink a bitmap to fit a surface.
  • repeat a bitmap on a surface.
  • put a bitmap on a surface that is not flat.
  • load, from file, a reasonable number of bitmap formats

We will deal with these problems in this module.

Texture

Using textures in OpenGL is according to Mark Kilgaard [2] an operation in 4 steps:

  1. Turn on (enable) textures
          glEnable(GL_TEXTURE_2D);
          
  2. Specify the texture
          glTexImage2D(...);
          
  3. Specify how the texture should be placed on a surface
          glTexEnvi(...);
          
  4. Draw by specifying coordinates on the surface and coordinates of the texture
          glBegin(GL_TRIANGLES);
            glTexCoord(...); glVertex3f(..)
            glTexCoord(...); glVertex3f(..)
            glTexCoord(...); glVertex3f(..)
          glEnd();
          

Specification of textures

There are a lot of methods and parameters in OpenGL to control textures on different forms, and there are a lot of possibilities for combining the material of a surface with textures. The ambitions here is not to give a full description of this options. We will concentrate on the basics. Full control over textures and visual effects is theme for trial and error based on the OpenGL documentation.

Turning on textures, glEnable(), and generating textures, glTexImage2D(), is fairly simple to understand from the OpenGL documentation.

We will look a little closer on how textures are placed on a surface. Again, we will only concentrate on basics. The possibilities are mush more numerous than shown below.

Important methods are:

  glTexParameteri(GL_TEXTURE_2D,...,...);
  glTexEnvi(GL_TEXTURE_ENV,...,...);

glTexParameter

There are in particular two properties we can control by glTexParameteri():

  • We can decide whether the texture should be locked to the geometry of the surface (clamp) or whether it should be repeated over the surface (repeat).

    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT)
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP)
          

    Note that GL_TEXTURE_WRAP_S is on of two directions in a 2D texture. The alternative is GL_TEXTURE_WRAP_T.

  • We can decide how a pixel should be rendered if a texture element covers less than or more than a pixel.

    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST)
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST)
          

    where an alternative to GL_NEAREST is GL_LINEAR. Note also that glTexParameter gives us a possibility to decide which mipmap we want to use. Mipmaps are alternative textures which offers more or less details, typically base on distance.

glTexEnv

glTexEnvi() lets us control how the texture should relate to the material of the surface it is placed on.

glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL)

will put the texture on the surface without bothering about the material of the surface.

Alternatives:

glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE)
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_BLEND)

has effects that are described in detail in the OpenGL documentation.

Geometry

Let us first look at some simple mechanisms to control the placing of a texture on a rectangle:

tekrek

Note that when we always assumes that a bitmap has size 1 in both directions, this has nothing to do with the physical size in pixels or image elements. The actual bitmap in this case is 64 x 64 pixels. The size of the rectangle we want to place the bitmap (texture) on is up to us, or the geometry of our model.

Note that OpenGL only accepts bitmaps with sizes 2n x 2m. n may be different from m.

Let us focus on the geometry and put a texture on some rectangles.

towers

  • Image 1 is rendered like this:
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
    ....
    
    glTexImage2D(..);
    glBegin(GL_POLYGON);
      glTexCoord2f(0.0f,0.0f);
      glVertex3f(-6.5f,-6.5f,0.1f);
    
      glTexCoord2f(1.0f,0.0f);
      glVertex3f(6.5f,-6.5f,0.1f);
    
      glTexCoord2f(1.0f,1.0f);
      glVertex3f(6.5f,6.5f,0.1f);
    
      glTexCoord2f(0.0f,1.0f);
      glVertex3f(-6.5f,6.5f,0.1f);
    glEnd();
    
  • Image 2 is rendered like this:
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
    ....
    
    glTexImage2D(..);
    glBegin(GL_POLYGON);
      glTexCoord2f(0.0f,0.0f);
      glVertex3f(-6.5f,-6.5f,0.1f);
    
      glTexCoord2f(3.0f,0.0f);
      glVertex3f(6.5f,-6.5f,0.1f);
    
      glTexCoord2f(3.0f,3.0f);
      glVertex3f(6.5f,6.5f,0.1f);
    
      glTexCoord2f(0.0f,3.0f);
      glVertex3f(-6.5f,6.5f,0.1f);
    glEnd();
    
  • The only difference between image 2 and image 3 is the first line:
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
      ...
    
  • In image 4 the first two lines are:
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
      ....
    

We see that we can connect corners in the geometry, glVertex3f(), with coordinates in the texture, glTexCoord2f(). This is simple and make perfect sense when have control over all corners. We can easily imagine that this is getting more complicated when we want to put textures on, say a Bezier surface.

There is, not surprisingly, a solution to this which is based on a mapping of the texture parallel to the mapping of the geometry. The code below puts a texture on a Bezier surface:

btower

...
// define ctrlpoints for beziersuface
GLfloat ctrlpoints[4][4][3] = // [v][u][xyz]
{
...
};
...
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);

glEnable(GL_TEXTURE_2D);
glEnable(GL_MAP2_VERTEX_3);
glEnable(GL_MAP2_TEXTURE_COORD_1);
glEnable(GL_MAP2_TEXTURE_COORD_2);

glTexImage2D(GL_TEXTURE_2D,0,3,
            m_theImage.GetWidth(),
            m_theImage.GetHeight(),
            0,GL_RGB,GL_UNSIGNED_BYTE,
            m_theImage.GetBitsPtr());

// map geometri
glMap2f(GL_MAP2_VERTEX_3,
        0.0f,1.0f,3,4,0.0f,1.0f,12,4,
        & ctrlpoints[0][0][0]);

// map texture
GLfloat txpts[2][2][2]={{{0.0, 0.0}, {1.0, 0.0}},
                       {{0.0, 1.0}, {1.0, 1.0}}};
glMap2f(GL_MAP2_TEXTURE_COORD_2,0,1,2,2,0,1,4,2,
        & txpts[0][0][0]);

glMapGrid2f(20,0.0f,1.0f,20,0.0f, 1.0f);

glEvalMesh2(GL_FILL, 0, 20, 0, 20);
References
  1. Dev IL, an imaging libraryopenil.sourceforge.net/14-03-2009
  1. Opengl Programming For The X Window SystemKilgard,Mark J.Addison-Wesley0201483599
  • Program which displays a texture on all 6 sides of a cube: https://svn.hiof.no/svn/psource/JOGL/tex1
    explained in: Textured Box
  • Program which displays a texture on a Bezier surface: https://svn.hiof.no/svn/psource/JOGL/tex2
    explained in: Bezier surface
Maintainance
B Stenseth, revised may 2009
(Welcome) OpenGL>Textures (Selection)