/* * lighting.c * * Shows effects of different light and material colors */ #include #include #include #include #include #include #include int windType; GLint windW, windH; /* Use a GLU sphere model */ GLUquadricObj *sphere; /* Define color values */ enum { Light_Ambient, Light_Diffuse, Light_Specular, Material_Ambient, Material_Diffuse, Material_Specular, Material_Shininess, Light_Specular_Is_Diffuse, Material_Ambient_Is_Diffuse, Copper_Color, Default_Color }; int ThisColor = Light_Diffuse; GLfloat Light_Position[4] = {0.0, 0.0, 1.0, 0.0}; /* Inifinite light source */ #define NUM_OF_COLOR_VECTORS 6 GLfloat RGBdefault[NUM_OF_COLOR_VECTORS][4] = { {0.0, 0.0, 0.0, 1.0}, /* Light_Ambient */ {1.0, 1.0, 1.0, 1.0}, /* Light_Diffuse */ {1.0, 1.0, 1.0, 1.0}, /* Light_Specular */ {0.2, 0.2, 0.2, 1.0}, /* Material_Ambient */ {0.8, 0.8, 0.8, 1.0}, /* Material_Diffuse */ {0.0, 0.0, 0.0, 1.0} /* Material_Specular */ }; GLfloat HSVdefault[NUM_OF_COLOR_VECTORS][3] = { {0.0, 0.0, 0.0}, /* Light_Ambient */ {0.0, 0.0, 1.0}, /* Light_Diffuse */ {0.0, 0.0, 1.0}, /* Light_Specular */ {0.0, 0.0, 0.2}, /* Material_Ambient */ {0.0, 0.0, 0.8}, /* Material_Diffuse */ {0.0, 0.0, 0.0} /* Material_Specular */ }; GLfloat ShinyDefault = 0.0; GLfloat RGBcopper[NUM_OF_COLOR_VECTORS][4] = { {0.2, 0.2, 0.2, 1.0}, /* Light_Ambient */ {1.0, 1.0, 1.0, 1.0}, /* Light_Diffuse */ {1.0, 1.0, 1.0, 1.0}, /* Light_Specular */ {0.19125, 0.0735, 0.0225, 1.0}, /* Material_Ambient */ {0.7038, 0.27048, 0.0828, 1.0}, /* Material_Diffuse */ {0.256777, 0.137622, 0.086014, 1.0} /* Material_Specular */ }; GLfloat HSVcopper[NUM_OF_COLOR_VECTORS][3] = { {0.0, 0.0, 0.2}, /* Light_Ambient */ {0.0, 0.0, 1.0}, /* Light_Diffuse */ {0.0, 0.0, 1.0}, /* Light_Specular */ {18.0, 0.88, 0.19}, /* Material_Ambient */ {18.0, 0.88, 0.7}, /* Material_Diffuse */ {18.0, 0.66, 0.25} /* Material_Specular */ }; GLfloat ShinyCopper = 12.8; GLfloat RGBcolor[NUM_OF_COLOR_VECTORS][4]; GLfloat HSVcolor[NUM_OF_COLOR_VECTORS][3]; GLfloat Shininess; /* Copy given RGB and HSV color values to current arrays */ void InitColors (GLfloat RGB[][4], GLfloat HSV[][3], GLfloat Shine) { int i, j; for (i=0; i< NUM_OF_COLOR_VECTORS; i++) { RGBcolor[i][0] = RGB[i][0]; RGBcolor[i][1] = RGB[i][1]; RGBcolor[i][2] = RGB[i][2]; RGBcolor[i][3] = RGB[i][3]; HSVcolor[i][0] = HSV[i][0]; HSVcolor[i][1] = HSV[i][1]; HSVcolor[i][2] = HSV[i][2]; } Shininess = Shine; } /* Copy source colors to destination colors */ void CopyColor (GLfloat RGBdest[3], GLfloat RGBsrc[3], GLfloat HSVdest[3], GLfloat HSVsrc[3]) { RGBdest[0] = RGBsrc[0]; RGBdest[1] = RGBsrc[1]; RGBdest[2] = RGBsrc[2]; HSVdest[0] = HSVsrc[0]; HSVdest[1] = HSVsrc[1]; HSVdest[2] = HSVsrc[2]; } /* Set background color, enable depth buffering */ static void Init(void) { /* Set background color */ glClearColor(0.0, 0.0, 0.0, 0.0); /* Enable depth buffer & lighting */ glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); /* Set default color = copper in white light */ InitColors (RGBcopper, HSVcopper, ShinyCopper); /* Create sphere */ sphere = gluNewQuadric(); gluQuadricDrawStyle(sphere, (GLenum)GLU_FILL); gluQuadricNormals(sphere, (GLenum)GLU_SMOOTH); glShadeModel(GL_SMOOTH); } /* Window size has changed: adjust viewport and perspective transformations */ static void Reshape(int width, int height) { GLdouble aspect; /* Adjust window size */ windW = (GLint)width; windH = (GLint)height; aspect = (GLdouble)windW / (GLdouble)windH; /* Viewport fills the entire window */ glViewport(0, 0, width, height); /* Use perspective projection */ glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective (60.0, aspect, 1.0, 1000.0); /* fovy, aspect, near, far */ /* Return to modelview mode */ glMatrixMode(GL_MODELVIEW); } /* Set colors in given RGBvector to colors specified by H,S,V */ void SetColorHSV (GLfloat RGBvector[3], GLfloat H, GLfloat S, GLfloat V) { int i; double f, p, q, t; /* no saturation = grey */ if (S == 0) { RGBvector[0] = RGBvector[1] = RGBvector[2] = V; } /* color has chromacity (hue) */ else { if (H >= 360) H -= 360.0; H /= 60.0; i = (int)H; f = H - i; p = V * (1 - S); q = V * (1 - (S * f)); t = V * (1 - (S * (1 - f))); switch (i) { case 0: RGBvector[0] = V; RGBvector[1] = t; RGBvector[2] = p; break; case 1: RGBvector[0] = q; RGBvector[1] = V; RGBvector[2] = p; break; case 2: RGBvector[0] = p; RGBvector[1] = V; RGBvector[2] = t; break; case 3: RGBvector[0] = p; RGBvector[1] = q; RGBvector[2] = V; break; case 4: RGBvector[0] = t; RGBvector[1] = p; RGBvector[2] = V; break; case 5: RGBvector[0] = V; RGBvector[1] = p; RGBvector[2] = q; break; } } } /* Arrow keys change colors of Light or Material, based on ThisColor */ static void Key2(int key, int x, int y) { if (ThisColor < Material_Shininess) { switch (key) { case GLUT_KEY_LEFT: /* change Hue */ HSVcolor[ThisColor][0] -= 1.0; if (HSVcolor[ThisColor][0] < 0) HSVcolor[ThisColor][0] += 360.0; SetColorHSV (RGBcolor[ThisColor], HSVcolor[ThisColor][0], HSVcolor[ThisColor][1], HSVcolor[ThisColor][2]); break; case GLUT_KEY_RIGHT: /* change Hue */ HSVcolor[ThisColor][0] += 1.0; if (HSVcolor[ThisColor][0] > 360) HSVcolor[ThisColor][0] -= 360.0; SetColorHSV (RGBcolor[ThisColor], HSVcolor[ThisColor][0], HSVcolor[ThisColor][1], HSVcolor[ThisColor][2]); break; case GLUT_KEY_UP: /* increase saturation */ HSVcolor[ThisColor][1] += 0.1; if (HSVcolor[ThisColor][1] > 1.0) HSVcolor[ThisColor][1] = 1.0; SetColorHSV (RGBcolor[ThisColor], HSVcolor[ThisColor][0], HSVcolor[ThisColor][1], HSVcolor[ThisColor][2]); break; case GLUT_KEY_DOWN: /* decrease saturation */ HSVcolor[ThisColor][1] -= 0.1; if (HSVcolor[ThisColor][1] < 0.0) HSVcolor[ThisColor][1] = 0.0; SetColorHSV (RGBcolor[ThisColor], HSVcolor[ThisColor][0], HSVcolor[ThisColor][1], HSVcolor[ThisColor][2]); break; default: return; } glutPostRedisplay(); /* force update of the display */ } } /* Handle other keys */ static void Key(unsigned char key, int x, int y) { switch (key) { case 27: /* ESC to quit */ exit(1); case '+': /* increase brightness */ if (ThisColor == Material_Shininess) { if (Shininess < 128.0) Shininess += 1.0; } else if ((ThisColor < Material_Shininess) && (HSVcolor[ThisColor][2] < 1.0)) { HSVcolor[ThisColor][2] += 0.1; SetColorHSV (RGBcolor[ThisColor], HSVcolor[ThisColor][0], HSVcolor[ThisColor][1], HSVcolor[ThisColor][2]); } break; case '-': /* decrease brightness */ if (ThisColor == Material_Shininess) { if (Shininess > 0.0) Shininess -= 1.0; } else if ((ThisColor < Material_Shininess) && (HSVcolor[ThisColor][2] > 0.0)) { HSVcolor[ThisColor][2] -= 0.1; SetColorHSV (RGBcolor[ThisColor], HSVcolor[ThisColor][0], HSVcolor[ThisColor][1], HSVcolor[ThisColor][2]); } break; case 'P': case 'p': printf ("Ambient light = (%f, %f, %f)\n", RGBcolor[0][0], RGBcolor[0][1], RGBcolor[0][2]); printf ("Diffuse light = (%f, %f, %f)\n", RGBcolor[1][0], RGBcolor[1][1], RGBcolor[1][2]); printf ("Specular light = (%f, %f, %f)\n", RGBcolor[2][0], RGBcolor[2][1], RGBcolor[2][2]); printf ("Ambient material = (%f, %f, %f)\n", RGBcolor[3][0], RGBcolor[3][1], RGBcolor[3][2]); printf ("Diffuse material = (%f, %f, %f)\n", RGBcolor[4][0], RGBcolor[4][1], RGBcolor[4][2]); printf ("Specular material = (%f, %f, %f)\n", RGBcolor[5][0], RGBcolor[5][1], RGBcolor[5][2]); printf ("Material shininess = %f\n", Shininess); default: return; } glutPostRedisplay(); /* force update of the display */ } /* Write out colors being affected by arrow keys & +/- GLUT functions for writing to screen */ void writeText(char *text) { char *c; int C; int x = 10; c = text; glRasterPos2i(x, 10); while (*c != '\0') { C = (int)(*c); glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, C); x += glutBitmapWidth(GLUT_BITMAP_TIMES_ROMAN_24, C); glRasterPos2i(x, 10); c++; } } void writeThisColor() { /* set the viewport for writing on */ glViewport(0, 0, windW, 30); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); gluOrtho2D(0, windW, 0, 30); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); /* write out the text */ glDisable(GL_LIGHTING); glColor3f(1.0, 1.0, 1.0); switch (ThisColor) { case Light_Ambient: writeText("Ambient Light"); break; case Light_Diffuse: writeText("Diffuse Light"); break; case Light_Specular: writeText("Specular Light"); break; case Material_Ambient: writeText("Ambient Material"); break; case Material_Diffuse: writeText("Diffuse Material"); break; case Material_Specular: writeText("Specular Material"); break; case Material_Shininess: writeText("Shininess of Material"); break; } glEnable(GL_LIGHTING); /* return to original viewport */ glViewport(0, 0, windW, windH); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); } /* Menu for changing colors & resetting position */ void color_menu(int id) { if (id <= Material_Shininess) { ThisColor = id; } else { switch (id) { case Light_Specular_Is_Diffuse: CopyColor(RGBcolor[Light_Specular], RGBcolor[Light_Diffuse], HSVcolor[Light_Specular], HSVcolor[Light_Diffuse]); ThisColor = Light_Specular; break; case Material_Ambient_Is_Diffuse: CopyColor(RGBcolor[Material_Ambient], RGBcolor[Material_Diffuse], HSVcolor[Material_Ambient], HSVcolor[Material_Diffuse]); ThisColor = Material_Ambient; break; case Copper_Color: InitColors (RGBcopper, HSVcopper, ShinyCopper); break; case Default_Color: InitColors (RGBdefault, HSVdefault, ShinyDefault); break; } } glutPostRedisplay(); /* force update of the display */ } void init_menu() { int lightmenuID, materialmenuID, copymenuID; // add to the light menu lightmenuID = glutCreateMenu(color_menu); glutAddMenuEntry("Ambient Light", Light_Ambient); glutAddMenuEntry("Diffuse Light", Light_Diffuse); glutAddMenuEntry("Specular Light", Light_Specular); // add to the material menu materialmenuID = glutCreateMenu(color_menu); glutAddMenuEntry("Ambient Material", Material_Ambient); glutAddMenuEntry("Diffuse Material", Material_Diffuse); glutAddMenuEntry("Specular Material", Material_Specular); glutAddMenuEntry("Material Shininess", Material_Shininess); // add to the light menu copymenuID = glutCreateMenu(color_menu); glutAddMenuEntry("Default Colors", Default_Color); glutAddMenuEntry("Copper Color", Copper_Color); glutAddMenuEntry("Set Light Specular = Diffuse", Light_Specular_Is_Diffuse); glutAddMenuEntry("Set Material Ambient = Diffuse", Material_Ambient_Is_Diffuse); glutCreateMenu(color_menu); glutAddSubMenu("Change Color of Light", lightmenuID); glutAddSubMenu("Change Color of Material", materialmenuID); glutAddSubMenu("Set Colors", copymenuID); glutAttachMenu(GLUT_RIGHT_BUTTON); } /* Set modeling and viewing transformations, then draw the letter polygons */ static void Draw(void) { /* clear the screen */ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* Set the illumination values */ glLoadIdentity(); // light position in world coordinates glLightfv(GL_LIGHT0, GL_POSITION, Light_Position); glLightfv(GL_LIGHT0, GL_AMBIENT, RGBcolor[Light_Ambient]); glLightfv(GL_LIGHT0, GL_DIFFUSE, RGBcolor[Light_Diffuse]); glLightfv(GL_LIGHT0, GL_SPECULAR, RGBcolor[Light_Specular]); glMaterialfv(GL_FRONT, GL_AMBIENT, RGBcolor[Material_Ambient]); glMaterialfv(GL_FRONT, GL_DIFFUSE, RGBcolor[Material_Diffuse]); glMaterialfv(GL_FRONT, GL_SPECULAR, RGBcolor[Material_Specular]); glMaterialf(GL_FRONT, GL_SHININESS, Shininess); /* Set the viewing transformation(s) */ /* NOTE: Transformations must be specified in reverse order! */ glLoadIdentity(); gluLookAt(0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); /* Draw the sphere */ gluSphere (sphere, 1.0, 30, 30); /* write out the value that's being changed */ writeThisColor(); glFlush(); /* force all changes to be applied to buffer */ glutSwapBuffers(); /* display what you just drew */ } void print_instructions(void) { char dummy; printf("TO CHANGE APPEARANCE OF THE SPHERE:\n"); printf("* Sub-menu (right mouse button) selects color to change\n"); printf("* Left-right arrows change hue\n"); printf(" (NOTE: if color is grey, increase saturation first!)\n"); printf("* Up-down arrows change saturation\n"); printf("* '+' and '-' change brightness or shininess\n"); printf("* 'P' or 'p' prints current values to stdout\n"); printf("\nPress Enter to start\n\n"); dummy = getchar(); // scanf("%c", dummy); } void main(int argc, char **argv) { /* Print out instructions before showing the window */ print_instructions(); /* Setup the window that logo will appear in */ windW = 300; windH = 300; glutInitWindowPosition(0, 0); glutInitWindowSize( windW, windH); windType = GLUT_DEPTH | GLUT_RGB| GLUT_DOUBLE; glutInitDisplayMode((GLenum)windType); if (glutCreateWindow("Lighting") == GL_FALSE) { exit(1); } Init(); init_menu(); glutReshapeFunc(Reshape); glutKeyboardFunc(Key); glutSpecialFunc(Key2); glutDisplayFunc(Draw); glutMainLoop(); }