/************************************************ * Sample Code for Lighting * WARNING: THIS CODE IS VERY VERY POORLY DOCUMENTED * READ AT YOUR OWN RISK! * Reading this code MAY harm your programming style. * Please avoid learning anything about programming from * this bit of code. It is here ONLY to demonstrate some * of the various functions in OpenGL. * In fact, it is best if you never saw this program * again. * * You have been warned. ************************************************/ // Include files: These may change slightly // Depending on the Operating System #include using namespace std; /* These are for a MAC */ #if defined (__MACOSX__) #include #include /* These are for Linux */ #elif defined (__linux) #include #include /* Otherwise, just try it with no subdirectory */ #else #include #include #endif #include #include "Time.H" // Frame parameters int frameWidth = 500; int frameHeight = 500; // Flags (toggle on/off) int lightOn = 1; int smooth = 0; int animate = 0; int lvFlag = GL_FALSE; // Variables used in animations float angle = 0; float deltaAngle = 1; float brightness = 1.0; void init(void) { glClearColor (0.0, 0.0, 0.0, 0.0); // Set up lighting and depth-test glEnable(GL_LIGHTING); glEnable(GL_DEPTH_TEST); // For z-buffering! } /**************** * Set the light up * Notice it is placed with vector 0,0,1 ****************/ void placeMainLight() { // Vector for light position (directional light - try a positional one) float rad = angle * 3.14159265/180.0; GLfloat light_position[] = { 3*cos(rad), 3*sin(rad), 1.0, 1.0 }; // Vector for Color of Light: Ambient, Diffuse, Specular // typically Diffuse and Specular are the same color GLfloat light_ambient[] = { 0.2*brightness, 0.2*brightness, 0.2*brightness, 1.0 }; GLfloat light_diffuse[] = { brightness, brightness, brightness, 1.0 }; GLfloat light_specular[] = { brightness, brightness, brightness, 1.0 }; // For Light 0, set the position, ambient, diffuse, and specular values glLightfv(GL_LIGHT0, GL_POSITION, light_position); glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular); // Constant attenuation (for distance, etc.) // Only works for fixed light locations! Otherwise disabled glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 1.0); glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.0); glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.0); glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, lvFlag); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE); glEnable(GL_LIGHT0); } /********* * setExperimental * Set material properties to mimic ?????? **********/ void setExperimental() { // Set its properties... (to be pewter-like) GLfloat ambient[] = { 0.10588, 0.058824, 0.113725, 1.0 }; GLfloat diffuse[] = { 0.927451, 0.470588, 0.541176, 1.0 }; GLfloat specular[] = { 0.333, 0.333, 0.521569, 1.0 }; // GLfloat emissive[] = { 0.0, 0.0, 0.5, 1.0 }; GLfloat shininess = 98.4615; glMaterialfv(GL_FRONT, GL_AMBIENT, ambient); glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, specular); // glMaterialfv(GL_FRONT, GL_EMISSION, emissive); // If you use it, remember to turn emission off afterwards! // That is, set to {0,0,0,1}. glMaterialf(GL_FRONT, GL_SHININESS, shininess); } /********* * setPewter * Set material properties to mimic pewter **********/ void setPewter() { // Set its properties... (to be pewter-like) GLfloat ambient[] = { 0.10588, 0.058824, 0.113725, 1.0 }; GLfloat diffuse[] = { 0.427451, 0.470588, 0.541176, 1.0 }; GLfloat specular[] = { 0.3333, 0.3333, 0.521569, 1.0 }; GLfloat shininess = 9.84615; glMaterialfv(GL_FRONT, GL_AMBIENT, ambient); glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, specular); glMaterialf(GL_FRONT, GL_SHININESS, shininess); } /********* * setCopper * Set material properties to mimic copper **********/ void setCopper() { // Set its properties... (to be copper-like) GLfloat ambient[] = { 0.19125, 0.0735, 0.0225, 1.0 }; GLfloat diffuse[] = { 0.7038, 0.27048, 0.0828, 1.0 }; GLfloat specular[] = { 0.256777, 0.137622, 0.086014, 1.0 }; // GLfloat shininess = 12.8; GLfloat shininess = 128.0; glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular); glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess); } GLfloat f(float i) { return sin(i*2)/10.0; } void drawFloor(float size, int levels) { glMatrixMode(GL_MODELVIEW); // Just to be sure we are talking about correct matrix glPushMatrix(); glTranslated(0,-2,0); // Move the floor down 2 units (visibility reasons) setPewter(); glNormal3f(0, 1, 0); glBegin(GL_QUADS); { float i, j; float step = 2*size / levels; for (i = -size; i < size; i += step) { for (j = -size; j < size; j += step) { glVertex3f(i,f(i),j+step); glVertex3f(i+step,f(i+step),j+step); glVertex3f(i+step,f(i+step),j); glVertex3f(i,f(i),j); } } } glEnd(); glPopMatrix(); } void drawCopperTeapot() { setCopper(); glFrontFace(GL_CW); // B/c teapot seems to have backwards normals (I think)??? glutSolidTeapot(1); glFrontFace(GL_CCW); } void drawCopperBall() { setExperimental(); glutSolidSphere(0.5, 50, 50); } /****************** * Draws the scene ******************/ void drawScene() { glMatrixMode(GL_MODELVIEW); // Just to be sure we are talking about correct matrix glPushMatrix(); drawFloor(5,40); drawCopperTeapot(); // at the origin glTranslated(0, 2, -2); drawCopperBall(); glPopMatrix(); } void display(void) { // clear the scene (both color and depth buffers!) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Set the shade model if (smooth) { glShadeModel(GL_SMOOTH); } else { glShadeModel(GL_FLAT); } // Fix the canonical view volume glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0, (float) frameWidth/(float) frameHeight, 1.0, 50.0); // Set up the camera glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0, 0, 15, // where am i? (the eye) 0, 0, 0, // what am i looking at? (lookAt) 0, 1, 0); // what is up anyway? (up vector) // Set up the light sources GLfloat amb[] = {0.8, 0.8, 0.8, 1.0}; glLightModelfv(GL_LIGHT_MODEL_AMBIENT, amb); if (lightOn) { placeMainLight(); } else { glDisable(GL_LIGHT0); } // Draw the floor and the object drawScene(); // Display the final scene. glutSwapBuffers(); } void keyboard(unsigned char key, int x, int y) { switch (key) { case 27: // escape key case 'q': // Perform a "fade" effect (a bit of a hack) for (int i = 0; i < 20; i++) { brightness = brightness/1.2; display(); } exit(0); break; case 'a': animate = !animate; break; case 'l': lightOn = !lightOn; // Toggle the main light glutPostRedisplay(); break; case 'h': printf("You'd like some help instructions, wouldn't you?\n"); break; case 's': smooth = !smooth; glutPostRedisplay(); break; case 'v': lvFlag = (lvFlag == GL_FALSE) ? GL_TRUE : GL_FALSE; glutPostRedisplay(); break; } } static Time lastTime; void idle() { if (!animate) { // No animation return; } Time currentTime; if (currentTime - lastTime > 25000) { lastTime = currentTime; // Do whatever needs to be animated here... angle += deltaAngle; if (angle >= 360) angle -= 360; else if (angle < 0) angle += 360; // And redisplay scene glutPostRedisplay(); } } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(frameWidth, frameHeight); glutInitWindowPosition(5, 5); glutCreateWindow(argv[0]); init(); glutDisplayFunc(display); glutKeyboardFunc(keyboard); glutIdleFunc(idle); glutMainLoop(); return 0; }