OpenGL:Tutorials:Tutorial Framework:Texture Mapping
From GPWiki
The wiki is now hosted by GameDev.NET at wiki.gamedev.net. All gpwiki.org content has been moved to the new server. However, the GPWiki forums are still active! Come say hello. Texture mapping is the application of an image to a polygon, this gives the illusion of detail without pushing up the poly count.
[edit] Loading the TextureFor this tutorial I have used our own TGA loader as the image loader. The code was simply cut and pasted into 'tga.h'.
I'm going to bundle up the texture loading into LoadTexture(), this function takes and filename and returns a GLuint texture handle.
GLuint TexID1,TexID2; // Handles to our textures
This could easily be an array or a struct of your own definition.
glGenTextures(1,&Texture); // Allocate space for texture glGenTextures() generates the texture handle in the second parameter, you can generate multiple handles by specifying the quantity in the first parameter and an array in the second.
Once we have our handle, we can bind to it: glBindTexture(GL_TEXTURE_2D,Texture); // Set our Tex handle as current This means that all subsequent texture operations will use the specified texture.
glTexImage2D(GL_TEXTURE_2D,0,3,Img.GetWidth(),Img.GetHeight(),0,GL_RGB,GL_UNSIGNED_BYTE,Img.GetImg()); The TGA image class is providing most of the information here, the width, height, img pointer as discussed above.
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP); glTexParameter() is another function that comes in a few flavours. Some versions accept float values or arrays as arguments. Here we just need to specify a filter to use on our texture when it is scaled. The most common filters are GL_NEAREST and GL_LINEAR. GL_LINEAR produces the best results, but GL_NEAREST is faster. We also specify texture wrapping behaviour here, GL_REPEAT means that texture coordinates outside the range 0.0 - 1.0 will produce duplicates of the texture, while GL_CLAMP stops any wrapping from occuring. Now our texture is ready for use.
[edit] Applying the TextureApplying the texture to a polygon is achieved by specifying texture coordinates alongside the vertices. First we have to enable texture mapping: glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,TexID1);
glBegin(GL_QUADS); glTexCoord2f(1.0f,1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glTexCoord2f(1.0f,0.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glTexCoord2f(0.0f,0.0f); glVertex3f( 1.0f, 1.0f,-1.0f); glTexCoord2f(0.0f,1.0f); glVertex3f(-1.0f, 1.0f,-1.0f); glEnd(); Again, the range of the texture coords is 0.0 - 1.0. This seems weird when the obvious measure for image maps is pixels. However, this system means that we can change the texture size and still use the same mapping coords to produce the same result. An easy way to calculate these coords is (Pixel X Pos / Image Width) and (Pixel Y Pos / Image Height). Remember that the behaviour or texture coords outside the range 0.0 - 1.0 will be defined by the TexParameter settings. Press 't' during the demo to see the texture mapped using partial sections around the side faces of the cube.
glDeleteTextures(1,&TexID1); glDeleteTextures(1,&TexID2);
[edit] Source CodeThe source to Render.cpp, compile this demo using the OpenGL Tutorial Framework. #include "Framework.h" #include "tga.h" GLuint LoadTexture(char *TexName); void Render(void) { GLuint TexID1,TexID2; // Handles to our textures float Rotate=0.0f; // A rotation value to be used to spin our polygon glClearColor(0,0,0,0); // Setup our screen glViewport(0,0,800,600); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f,800.0f/600.0f,1.0f,500.0f); glMatrixMode(GL_MODELVIEW); // Ensure correct display of polygons glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); glDepthMask(GL_TRUE); // Load the textures TexID1=LoadTexture("Logo.tga"); TexID2=LoadTexture("Logo2.tga"); // This loop will run until Esc is pressed while(RunLevel) { if(Keys[VK_ESCAPE]) // Esc Key RunLevel=0; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); // Reset current matrix (Modelview) // Do our rotations glTranslatef(0.0f,0.0f,-5.0f); glRotatef(Rotate,0.0f,0.0f,1.0f); glRotatef(Rotate,1.0f,0.6f,0.0f); // Enable texturing and select first texture glColor3f(1.0f,1.0f,1.0f); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D,TexID1); // Draw the top face glBegin(GL_QUADS); glTexCoord2f(1.0f,1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glTexCoord2f(1.0f,0.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glTexCoord2f(0.0f,0.0f); glVertex3f( 1.0f, 1.0f,-1.0f); glTexCoord2f(0.0f,1.0f); glVertex3f(-1.0f, 1.0f,-1.0f); glEnd(); // Select second texture glBindTexture(GL_TEXTURE_2D,TexID2); glBegin(GL_QUADS); glTexCoord2f(1.0f,0.0f); glVertex3f(-1.0f,-1.0f, 1.0f); glTexCoord2f(0.0f,0.0f); glVertex3f(-1.0f,-1.0f,-1.0f); glTexCoord2f(0.0f,1.0f); glVertex3f( 1.0f,-1.0f,-1.0f); glTexCoord2f(1.0f,1.0f); glVertex3f( 1.0f,-1.0f, 1.0f); glEnd(); // Press 't' to texture the side faces if(Keys['T']) { glEnable(GL_TEXTURE_2D); // Draw textured side faces glBegin(GL_TRIANGLE_STRIP); glTexCoord2f(1.0f,0.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glTexCoord2f(0.0f,0.0f); glVertex3f(-1.0f,-1.0f, 1.0f); glTexCoord2f(1.0f,0.3f); glVertex3f( 1.0f, 1.0f, 1.0f); glTexCoord2f(0.0f,0.3f); glVertex3f( 1.0f,-1.0f, 1.0f); glTexCoord2f(1.0f,0.5f); glVertex3f( 1.0f, 1.0f,-1.0f); glTexCoord2f(0.0f,0.5f); glVertex3f( 1.0f,-1.0f,-1.0f); glTexCoord2f(1.0f,0.75f); glVertex3f(-1.0f, 1.0f,-1.0f); glTexCoord2f(0.0f,0.75f); glVertex3f(-1.0f,-1.0f,-1.0f); glTexCoord2f(1.0f,0.95f); glVertex3f(-1.0f, 1.0f, 1.0f); glTexCoord2f(0.0f,0.95f); glVertex3f(-1.0f,-1.0f, 1.0f); glEnd(); } else { glDisable(GL_TEXTURE_2D); // Draw colored side faces glBegin(GL_TRIANGLE_STRIP); glColor3f(0.8f,0.8f,0.8f); // Gray glVertex3f(-1.0f, 1.0f, 1.0f); glVertex3f(-1.0f,-1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glColor3f(0.0f,1.0f,0.0f); // Green glVertex3f( 1.0f,-1.0f, 1.0f); glColor3f(1.0f,1.0f,0.0f); // Yellow glVertex3f( 1.0f, 1.0f,-1.0f); glColor3f(0.0f,1.0f,1.0f); // Aqua? glVertex3f( 1.0f,-1.0f,-1.0f); glColor3f(0.6f,0.6f,0.6f); // Gray glVertex3f(-1.0f, 1.0f,-1.0f); glColor3f(0.1f,0.1f,0.1f); // Dark Gray glVertex3f(-1.0f,-1.0f,-1.0f); glColor3f(0.0f,0.0f,1.0f); // Blue glVertex3f(-1.0f, 1.0f, 1.0f); glColor3f(1.0f,0.0f,1.0f); // Red glVertex3f(-1.0f,-1.0f, 1.0f); glEnd(); } // Add to the rotation for next frame Rotate+=0.05f; // Show our cube FlipBuffers(); } // Clean up glDeleteTextures(1,&TexID1); glDeleteTextures(1,&TexID2); } GLuint LoadTexture(char *TexName) { TGAImg Img; // Image loader GLuint Texture; // Load our Texture if(Img.Load(TexName)!=IMG_OK) return -1; glGenTextures(1,&Texture); // Allocate space for texture glBindTexture(GL_TEXTURE_2D,Texture); // Set our Tex handle as current // Create the texture if(Img.GetBPP()==24) glTexImage2D(GL_TEXTURE_2D,0,3,Img.GetWidth(),Img.GetHeight(),0, GL_RGB,GL_UNSIGNED_BYTE,Img.GetImg()); else if(Img.GetBPP()==32) glTexImage2D(GL_TEXTURE_2D,0,4,Img.GetWidth(),Img.GetHeight(),0, GL_RGBA,GL_UNSIGNED_BYTE,Img.GetImg()); else return -1; // Specify filtering and edge actions glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP); return Texture; } [edit] DownloadsOpenGL_Tut3_(TexMap).zip - A zip including all source code, image files and Win32 exe. |



