This program will use the following features from OpenGL: glGenTextures, glBindTexture, glTexImage2D, glTexParameteri and glTexCoord2f.
To use textures in OpenGL, you have to load the image data into your programs memory. For DIBs and BMPs, you probably want to load them into a buffer of type unsigned char *. DIBs and BMPs requires special routine for proper loading. In this example, we are using the RAW file format.
There might be many textures that will be used in your program. In OpenGL, every textures are identified by unique integers. These integers are generated with a call to glGenTextures. You still have to call glGenTextures even if you have only one texture.
For each texture, we first make a call to glBindTexture to tell OpenGL which texture we will be processing. Then, we call glTexImage2D to tell OpenGL the details regarding the texture, such as the width, height, format of the data and the image itself. Because the image size most probably does not fit exactly as the width and height of the QUAD, we have to specify the filter functions to use with the function glTexParameteri when the image is smaller than the targetted QUAD, and when the image is larger than the target QUAD.
Finally, we call glTexCoord2f to specify the texture coordinates (u,v), and call glVertex3f (x,y,z) for the corresponding vertex of the QUAD.
Make sure that GL_TEXTURE_2D is enabled.
#ifdef WIN32 #include <windows.h> #endif #include <stdio.h> // for file handling #include <io.h> #include <glut.h> void Initialize(void); void Display(void); void Reshape(int w, int h); void Keyboard (unsigned char key, int x, int y); void DrawFloor(void); void DrawTexturedCube(GLdouble size, GLdouble x_offset,GLdouble y_offset, GLdouble z_offset, GLint rot_x, GLint rot_y, GLint rot_z, GLint tex_front, GLint tex_back, GLint tex_top, GLint tex_bottom, GLint tex_left, GLint tex_right ); bool LoadTextures(void); unsigned char * LoadRAW(char * filename); #define NUM_TEXTURES 1 // number of textures char * TextureFiles[] = {"4sides.raw",0}; bool AntialiasToggle = false; bool TextureToggle = true; GLuint TextureMap[NUM_TEXTURES]; // for the texture names int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { Initialize(); glutMainLoop(); return 0; } void Initialize(void) { int argc; char * argv[] = {"dummy",0}; argc = 1; glutInit(&argc, (char **)&argv[0]); glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH|GLUT_ALPHA); glutInitWindowSize(300, 300); glutInitWindowPosition(-1, -1); // Let window to determine the startup position glutCreateWindow("Two Texture Mapped Cubes"); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Sets the background color - R, G, B, and alpha glShadeModel(GL_SMOOTH); // One of GL_SMOOTH or GL_FLAT glBlendFunc (GL_SRC_ALPHA_SATURATE, GL_ONE); glColorMaterial(GL_FRONT,GL_SPECULAR); // Makes the coloring work for basic primitives glCullFace(GL_BACK); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); // Enable a single light source glEnable(GL_COLOR_MATERIAL); glEnable(GL_CULL_FACE); glEnable(GL_TEXTURE_2D); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Nicest perspective output // Register GLUT callback functions glutDisplayFunc(Display); // Register Display() function glutReshapeFunc(Reshape); // Register Reshape() function glutKeyboardFunc(Keyboard); // Register Keyboard() function // Load the textures if (!LoadTextures()) { exit(1); } } bool LoadTextures(void) { unsigned char * image; int i; glGenTextures(NUM_TEXTURES, &TextureMap[0]); // Generate texture names for (i=0;i<NUM_TEXTURES;i++) { glBindTexture(GL_TEXTURE_2D, TextureMap[i]); image = LoadRAW(TextureFiles[i]); if (image) { glTexImage2D(GL_TEXTURE_2D, 0, 3, (GLint)128, (GLint)128, 0, GL_RGB, GL_UNSIGNED_BYTE, image); free(image); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // Linear Filtering glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // Linear Filtering } else return false; } return true; } unsigned char * LoadRAW(char * filename) { unsigned char * ImageData = NULL; int PixelPos; FILE * Fin; unsigned char Buffer[256]; long ByteCount; if ((Fin = fopen(filename,"rb"))!=NULL) // open file for read only, binary { while ((ByteCount = fread(Buffer,1,256,Fin))>0) { if (ImageData) { ImageData = (BYTE *)realloc(ImageData,ByteCount + PixelPos); if (!ImageData) { MessageBox(NULL,"Error allocating memory.","",MB_OK); fclose(Fin); return NULL; } } else { ImageData = (BYTE *)malloc(ByteCount); PixelPos = 0; if (!ImageData) { MessageBox(NULL,"Error allocating memory.","",MB_OK); fclose(Fin); return NULL; } } memcpy(ImageData + PixelPos,Buffer,ByteCount); PixelPos= PixelPos + ByteCount; } fclose(Fin); return ImageData; } else { MessageBox(NULL,"Error openning file.","",MB_OK); return NULL; } } void Reshape(int w, int h) { double range = 2; glViewport(0,0,w,h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-range,range,-range,range,-range,range); gluPerspective(30,1,1,20); glTranslatef(0,0,-4); } void Keyboard (unsigned char key, int x, int y) { // Keyboard events can be intepreted here with a switch-case structure switch (key) { case 'a': AntialiasToggle = !AntialiasToggle; glutPostRedisplay(); break; case 't': TextureToggle = !TextureToggle; glutPostRedisplay(); break; default: break; } } void Display(void) { if (AntialiasToggle) { glClear(GL_COLOR_BUFFER_BIT); glDisable(GL_DEPTH_TEST); glEnable(GL_BLEND); glEnable(GL_POLYGON_SMOOTH); } else { glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_TEST); glDisable(GL_BLEND); glDisable(GL_POLYGON_SMOOTH); } if (TextureToggle) glEnable(GL_TEXTURE_2D); else glDisable(GL_TEXTURE_2D); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); DrawTexturedCube(1.0f, // size 1.0f,0.5f,0, // offset 30,30,0, // rotation 0,0,0,0,0,0); // textures DrawTexturedCube(1.0f, -1.0f,0.5f,0, 30,30,0, 0,0,0,0,0,0); // textures glutSwapBuffers(); // swap the display buffer to show the new results } void DrawTexturedCube(GLdouble size, GLdouble x_offset, GLdouble y_offset, GLdouble z_offset, GLint rot_x, GLint rot_y, GLint rot_z, GLint tex_front, GLint tex_back, GLint tex_top, GLint tex_bottom, GLint tex_left, GLint tex_right ) { GLdouble HL; // half length for the sides of cube HL = size / 2.0f; glPushMatrix(); glTranslatef(x_offset,y_offset,z_offset); glPushMatrix(); glRotatef(rot_x,1,0,0); glRotatef(rot_y,0,1,0); glRotatef(rot_z,0,0,1); // Front Face glBindTexture(GL_TEXTURE_2D, TextureMap[tex_front]); glBegin(GL_QUADS); if (TextureToggle) glTexCoord2f(0.0f, 0.0f); glVertex3f(-HL,-HL, HL); if (TextureToggle) glTexCoord2f(1.0f, 0.0f); glVertex3f( HL,-HL, HL); if (TextureToggle) glTexCoord2f(1.0f, 1.0f); glVertex3f( HL, HL, HL); if (TextureToggle) glTexCoord2f(0.0f, 1.0f); glVertex3f(-HL, HL, HL); glEnd(); // Back Face glBindTexture(GL_TEXTURE_2D, TextureMap[tex_back]); glBegin(GL_QUADS); if (TextureToggle) glTexCoord2f(1.0f, 0.0f); glVertex3f(-HL,-HL,-HL); if (TextureToggle) glTexCoord2f(1.0f, 1.0f); glVertex3f(-HL, HL,-HL); if (TextureToggle) glTexCoord2f(0.0f, 1.0f); glVertex3f( HL, HL,-HL); if (TextureToggle) glTexCoord2f(0.0f, 0.0f); glVertex3f( HL,-HL,-HL); glEnd(); // Top Face glBindTexture(GL_TEXTURE_2D, TextureMap[tex_top]); glBegin(GL_QUADS); if (TextureToggle) glTexCoord2f(0.0f, 1.0f); glVertex3f(-HL, HL,-HL); if (TextureToggle) glTexCoord2f(0.0f, 0.0f); glVertex3f(-HL, HL, HL); if (TextureToggle) glTexCoord2f(1.0f, 0.0f); glVertex3f( HL, HL, HL); if (TextureToggle) glTexCoord2f(1.0f, 1.0f); glVertex3f( HL, HL,-HL); glEnd(); // Bottom Face glBindTexture(GL_TEXTURE_2D, TextureMap[tex_bottom]); glBegin(GL_QUADS); if (TextureToggle) glTexCoord2f(1.0f, 1.0f); glVertex3f(-HL,-HL,-HL); if (TextureToggle) glTexCoord2f(0.0f, 1.0f); glVertex3f( HL,-HL,-HL); if (TextureToggle) glTexCoord2f(0.0f, 0.0f); glVertex3f( HL,-HL, HL); if (TextureToggle) glTexCoord2f(1.0f, 0.0f); glVertex3f(-HL,-HL, HL); glEnd(); // Left Face glBindTexture(GL_TEXTURE_2D, TextureMap[tex_left]); glBegin(GL_QUADS); if (TextureToggle) glTexCoord2f(0.0f, 0.0f); glVertex3f(-HL,-HL,-HL); if (TextureToggle) glTexCoord2f(1.0f, 0.0f); glVertex3f(-HL,-HL, HL); if (TextureToggle) glTexCoord2f(1.0f, 1.0f); glVertex3f(-HL, HL, HL); if (TextureToggle) glTexCoord2f(0.0f, 1.0f); glVertex3f(-HL, HL,-HL); glEnd(); // Right face glBindTexture(GL_TEXTURE_2D, TextureMap[tex_right]); glBegin(GL_QUADS); if (TextureToggle) glTexCoord2f(1.0f, 0.0f); glVertex3f( HL,-HL,-HL); if (TextureToggle) glTexCoord2f(1.0f, 1.0f); glVertex3f( HL, HL,-HL); if (TextureToggle) glTexCoord2f(0.0f, 1.0f); glVertex3f( HL, HL, HL); if (TextureToggle) glTexCoord2f(0.0f, 0.0f); glVertex3f( HL,-HL, HL); glEnd(); glPopMatrix(); glPopMatrix(); }: : go back : :