/////////////////////////////////////////////////////////////////////////////////////////////////////// // loadTextures.cpp // // This stripped-down program shows how to load both external and program-generated images as textures. // // Interaction: // Press the left and right arrow keys to rotate the square. // Press space to toggle between textures. // Press delete to reset. // // Sumanta Guha // // Texture Credits: See ExperimenterSource/Textures/TEXTURE_CREDITS.txt /////////////////////////////////////////////////////////////////////////////////////////////////////// #include #include #include # include # include # include #include "getbmp.h" using namespace std; // Globals. static unsigned int texture[2]; // Array of texture ids. static unsigned char chessboard[64][64][4]; // Storage for chessboard image. static float angle = 0.0; // Angle to rotate textured square. static int id = 0; // Currently displayed texture id. GLfloat S_MIN, S_MAX, T_MIN, T_MAX; // Load external textures. void loadExternalTextures() { // Local storage for bmp image data. BitMapFile *image[1]; // Load the image. image[0] = getbmp("../Textures/launch.bmp"); // Create texture object texture[0]. glBindTexture(GL_TEXTURE_2D, texture[0]); // Specify image data for currently active texture object. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image[0]->sizeX, image[0]->sizeY, 0, GL_RGBA, GL_UNSIGNED_BYTE, image[0]->data); // Set texture parameters for wrapping. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // Set texture parameters for filtering. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); } // Routine to load a program-generated image as a texture. void loadProceduralTextures() { // Create texture object texture[1]. glBindTexture(GL_TEXTURE_2D, texture[1]); // Specify image data for currently active texture object. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, chessboard); // Set texture parameters for wrapping. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // Set texture parameters for filtering. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); } // Create 64 x 64 RGBA image of a chessboard. void createChessboard(void) { int i, j; for (i = 0; i < 64; i++) for (j = 0; j < 64; j++) if ( ( ((i/8)%2) && ((j/8)%2) ) || ( !((i/8)%2) && !((j/8)%2) ) ) { chessboard[i][j][0] = 0x00; chessboard[i][j][1] = 0x00; chessboard[i][j][2] = 0x00; chessboard[i][j][3] = 0xFF; } else { chessboard[i][j][0] = 0xFF; chessboard[i][j][1] = 0xFF; chessboard[i][j][2] = 0xFF; chessboard[i][j][3] = 0xFF; } } void reset(void) { S_MIN = 0; S_MAX = 1; T_MIN = 0; T_MAX = 1; return; } // Initialization routine. void setup(void) { reset(); glClearColor(0.8, 0.8, 0.8, 0.0); // Create texture ids. glGenTextures(2, texture); // Load external texture. loadExternalTextures(); // Generate procedural texture. createChessboard(); // Load procedural texture. loadProceduralTextures(); // Specify how texture values combine with current surface color values. glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); // Turn on OpenGL texturing. glEnable(GL_TEXTURE_2D); } // Drawing routine. void drawScene(void) { glClear(GL_COLOR_BUFFER_BIT); glLoadIdentity(); gluLookAt(0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); glRotatef(angle, 0.0, 1.0, 0.0); // Activate texture object. glBindTexture(GL_TEXTURE_2D, texture[id]); // Map the texture onto a square polygon. glBegin(GL_POLYGON); glTexCoord2f(S_MIN, T_MIN); glVertex3f(-10.0, -10.0, 0.0); glTexCoord2f(S_MAX, T_MIN); glVertex3f(10.0, -10.0, 0.0); glTexCoord2f(S_MAX, T_MAX); glVertex3f(10.0, 10.0, 0.0); glTexCoord2f(S_MIN, T_MAX); glVertex3f(-10.0, 10.0, 0.0); glEnd(); glutSwapBuffers(); } // OpenGL window reshape routine. void resize(int w, int h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-5.0, 5.0, -5.0, 5.0, 5.0, 100.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } // Keyboard input processing routine. void keyInput(unsigned char key, int x, int y) { switch(key) { case 's': S_MIN -= 1; break; case 'S': S_MIN += 1; break; case 't': T_MIN -= 1; break; case 'T': T_MIN += 1; break; case 'a': S_MAX -= 1; break; case 'A': S_MAX += 1; break; case 'r': T_MAX -= 1; break; case 'R': T_MAX += 1; break; case 'q': case 27: exit(0); break; case ' ': id++; if (id == 2) id = 0; break; case 127: angle = 0.0; break; default: break; } glutPostRedisplay(); } // Callback routine for non-ASCII key entry. void specialKeyInput(int key, int x, int y) { if (key == GLUT_KEY_LEFT) { angle -= 5.0; if (angle < 0.0) angle += 360.0; } if (key == GLUT_KEY_RIGHT) { angle += 5.0; if (angle > 360.0) angle -= 360.0; } glutPostRedisplay(); } // Routine to output interaction instructions to the C++ window. void printInteraction(void) { cout << "\tInteraction:" << endl; cout << "\tPress the left and right arrow keys to rotate the square." << endl << "\tPress space to toggle between textures." << endl << "\tPress delete to reset." << endl; cout << " s/S chang texture s min coordinates " << endl; cout << " a/A chang texture s max coordinates " << endl; cout << " t/T chang texture t min coordinates " << endl; cout << " r/R chang texture t max coordinates " << endl; } // Main routine. int main(int argc, char **argv) { printInteraction(); glutInit(&argc, argv); glutInitContextVersion(3, 0); glutInitContextProfile(GLUT_COMPATIBILITY_PROFILE); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA); glutInitWindowSize(500, 500); glutCreateWindow(argv[0]); glutDisplayFunc(drawScene); glutReshapeFunc(resize); glutKeyboardFunc(keyInput); glutSpecialFunc(specialKeyInput); glewExperimental = GL_TRUE; glewInit(); setup(); glutMainLoop(); }