A Texture Mapping Technique Using OpenGL


Application Security Testing: An Integral Part of DevOps

Environment: VC++6, Win32


Rendering an image on the surface of an object can be accomplished with just a few steps by using OpenGL. My last article on OpenGL demonstrated a simple method for drawing OpenGL output directly to a device independent bitmap (DIB), and for loading OpenGL commands into a call list to make rendering more efficient. This article builds on that framework and demonstrates how to overlay an image on the surface of an object. In this example, the object surfaces are spheres and the textures are images representing some of the planets in our solar system.

The following steps can be used to texture map objects:

  1. Load each texture into a 24-bit DIBSection object. (A regular DIB will do, but making it a DIB section doesn't hurt.)
  2. Tell the OpenGL library how your image is laid out by calling glTexImage2D. You can specify the image as RGB, or BGR, and so forth. Note: the width and height of the image can be different, but the dimensions have to each be powers of 2 plus any border width you specify in the call to glTexImage2D.
  3. As you build your model by specifying vertices, use the glTexCoord2d to specify the location within the texture image corresponding to each model vertex. Note: the image coordinates are scaled from 0 to 1; so, if your image is 100x100 pixels wide and you want to connect a vertex with the center pixel, you call glTexCoord2d(0.50,0.50).

Thats it! You're done.

In case you want to take texture mapping a little farther, there are two other things worth investigating:

The function glTexImage2D provides support for mip-mapping. Mip-mapping is basically when you use multiple images of the same thing at different resolutions. Let's say you want to map an image of the Earth onto a sphere. Using a smaller texture image will improve performance without ruining the model as long as the sphere is small. When the sphere is large (takes up a significant portion of the screen), you might want a higher-resolution image to avoid stretching artifacts: mip-mapping allows you to do that.

Another variation on texture mapping can be accomplished by using the glTexEnvf function. In the sample project, I used the following call: glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);. However, you may replace GL_DECAL with GL_BLEND or GL_MODULATE to get a different texturing effect.

The following code sample shows how to actually connect image coordinates with your model's vertices:

namespace GEO {
  const double PI = 3.14159265359;
  const double TWOPI = 6.28318530718;
  const double DE2RA = 0.01745329252;
  const double RA2DE = 57.2957795129;
  const double FLATTENING = 1.0/298.26;
  const double PIOVER2 = 1.570796326795;

if (m_have_texture)



  glEnable( GL_TEXTURE_2D );
  glDisable( GL_TEXTURE_2D );

glBegin( GL_TRIANGLES );

start_lat = -90;
start_lon = 0.0;
R = 1.0;

lat_incr = 180.0 / NumLatitudes;
lon_incr = 360.0 / NumLongitudes;

int row, col;

for (col = 0; col < NumLongitudes; col++){
  phi1 = (start_lon + col * lon_incr) * GEO::DE2RA;
  phi2 = (start_lon + (col + 1) * lon_incr) * GEO::DE2RA;
  for (row = 0; row < NumLatitudes; row++){
    theta1 = (start_lat + row * lat_incr) * GEO::DE2RA;
    theta2 = (start_lat + (row + 1) * lat_incr) * GEO::DE2RA;

    u[0] = R * cos(phi1) * cos(theta1);    //x
    u[1] = R * sin(theta1);                //y
    u[2] = R * sin(phi1) * cos(theta1);    //z

    v[0] = R * cos(phi1) * cos(theta2);    //x
    v[1] = R * sin(theta2);                //y
    v[2] = R * sin(phi1) * cos(theta2);    //z

    w[0] = R * cos(phi2) * cos(theta2);    //x
    w[1] = R * sin(theta2);                //y
    w[2] = R * sin(phi2) * cos(theta2);    //z

    glTexCoord2d((180.0 - phi1*GEO::RA2DE)/360.0,
                 (theta1 + GEO::PIOVER2)*GEO::RA2DE/180.0);
    glTexCoord2d((180.0 - phi1*GEO::RA2DE)/360.0,
                 (theta2 + GEO::PIOVER2)*GEO::RA2DE/180.0);
    glTexCoord2d((180.0 - phi2*GEO::RA2DE)/360.0,
                 (theta2 + GEO::PIOVER2)*GEO::RA2DE/180.0);

    v[0] = R * cos(phi2) * cos(theta1);    //x
    v[1] = R * sin(theta1);                //y
    v[2] = R * sin(phi2) * cos(theta1);    //z

    glTexCoord2d((180.0 - phi1*GEO::RA2DE)/360.0,
                 (theta1 + GEO::PIOVER2)*GEO::RA2DE/180.0);
    glTexCoord2d((180.0 - phi2*GEO::RA2DE)/360.0,
                 (theta2 + GEO::PIOVER2)*GEO::RA2DE/180.0);
    glTexCoord2d((180.0 - phi2*GEO::RA2DE)/360.0,
                 (theta1 + GEO::PIOVER2)*GEO::RA2DE/180.0);

    glDisable( GL_TEXTURE_2D );


Sample Project

I only have textures for the Earth, Mars, Jupiter, and Saturn, so I just picked a color for the other planets. If time permitted, it would be nice to see a ring around Saturn.



Download demo project - 405 Kb

About the Author

Andy McGovern

Andy McGovern - Software Developer/Engineer. Special interests: astronomy, image processing, orbital mechanics, mathematics. Currently work at the Johns Hopkins University Applied Physics Laboratory on the science operations team for the CRISM instrument on the Mars Reconnaissance Orbiter.


  • Compressed textures

    Posted by Legacy on 04/03/2003 12:00am

    Originally posted by: U'dragon

    What would be really nice is an example of using compressed textures with OpenGL under Windows.

    Can't seem to find anything related to that in the MSDN.

  • why don't you insert a rendered image with this article ?!

    Posted by Legacy on 04/02/2003 12:00am

    Originally posted by: Zhefu Zhang

    why don't you insert a rendered image with this article ?!

  • You must have javascript enabled in order to post comments.

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • As all sorts of data becomes available for storage, analysis and retrieval - so called 'Big Data' - there are potentially huge benefits, but equally huge challenges...
  • The agile organization needs knowledge to act on, quickly and effectively. Though many organizations are clamouring for "Big Data", not nearly as many know what to do with it...
  • Cloud-based integration solutions can be confusing. Adding to the confusion are the multiple ways IT departments can deliver such integration...

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date
We have made updates to our Privacy Policy to reflect the implementation of the General Data Protection Regulation.