/* $Id: gloss.c,v 1.4.4.1 2000/08/29 21:17:25 brianp Exp $ */ /* * Specular reflection demo. The specular highlight is modulated by * a sphere-mapped texture. The result is a high-gloss surface. * NOTE: you really need hardware acceleration for this. * Also note, this technique can't be implemented with multi-texture * and separate specular color interpolation because there's no way * to indicate that the second texture unit (the reflection map) * should modulate the specular color and not the base color. * A future multi-texture extension could fix that. * * Command line options: * -info print GL implementation information * * * Brian Paul October 22, 1999 This program is in the public domain. */ #include #include #include #include #include #include #include #include #include "ReadTex2.h" /* I know, this is a hack. */ #include "ModuleManipulateur.h" #include "ModuleReshape.h" #define SPECULAR_TEXTURE_FILE "reflect.rgb" #define BASE_TEXTURE_FILE "tile.rgb" /* Menu items */ #define DO_SPEC_TEXTURE 1 #define OBJECT 2 #define ANIMATE 3 #define QUIT 100 static GLuint CylinderObj = 0; static GLuint TeapotObj = 0; static GLuint Object = 0; static GLboolean Animate = GL_TRUE; static GLfloat Xrot = 0.0, Yrot = 0.0, Zrot = 0.0; static GLfloat DXrot = 1.0, DYrot = 2.5; static GLfloat Black[4] = { 0, 0, 0, 0 }; static GLfloat White[4] = { 1, 1, 1, 1 }; static GLfloat Diffuse[4] = { .3F, .3F, 1.0F, 1.0F }; /* blue */ static GLfloat Shininess = 6; static GLuint BaseTexture, SpecularTexture; static GLboolean DoSpecTexture = GL_TRUE; /* performance info */ static GLint T0 = 0; static GLint Frames = 0; static void Idle( void ) { if (Animate) { Xrot += DXrot; Yrot += DYrot; glutPostRedisplay(); } } static void Display( void ) { glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glPushMatrix(); glRotatef(Xrot, 1.0, 0.0, 0.0); glRotatef(Yrot, 0.0, 1.0, 0.0); glRotatef(Zrot, 0.0, 0.0, 1.0); manipulateurSouris(); manipulateurClavier(); /* First pass: diffuse lighting with base texture */ glMaterialfv(GL_FRONT, GL_DIFFUSE, Diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, Black); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, BaseTexture); glCallList(Object); /* Second pass: specular lighting with reflection texture */ glBlendFunc(GL_ONE, GL_ONE); /* add */ glEnable(GL_BLEND); glDepthFunc(GL_LEQUAL); glMaterialfv(GL_FRONT, GL_DIFFUSE, Black); glMaterialfv(GL_FRONT, GL_SPECULAR, White); if (DoSpecTexture) { glBindTexture(GL_TEXTURE_2D, SpecularTexture); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); } else { glDisable(GL_TEXTURE_2D); } glCallList(Object); glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); glDisable(GL_BLEND); glPopMatrix(); glutSwapBuffers(); if (Animate) { GLint t = glutGet(GLUT_ELAPSED_TIME); Frames++; if (t - T0 >= 5000) { GLfloat seconds = (t - T0) / 1000.0; GLfloat fps = Frames / seconds; printf("%d frames in %g seconds = %g FPS\n", Frames, seconds, fps); T0 = t; Frames = 0; } } } static void ToggleAnimate(void) { Animate = !Animate; if (Animate) { glutIdleFunc( Idle ); T0 = glutGet(GLUT_ELAPSED_TIME); Frames = 0; } else { glutIdleFunc( NULL ); } } static void ModeMenu(int entry) { if (entry==ANIMATE) { ToggleAnimate(); } else if (entry==DO_SPEC_TEXTURE) { DoSpecTexture = !DoSpecTexture; } else if (entry==OBJECT) { if (Object == TeapotObj) Object = CylinderObj; else Object = TeapotObj; } else if (entry==QUIT) { exit(0); } glutPostRedisplay(); } void key(unsigned char key,int x,int y) { if ( keyManipulateur(key,x,y) ) glutPostRedisplay(); else { (void) x; (void) y; switch (key) { case 's': Shininess--; if (Shininess < 0.0) Shininess = 0.0; glMaterialf(GL_FRONT, GL_SHININESS, Shininess); printf("Shininess = %g\n", Shininess); break; case 'S': Shininess++; if (Shininess > 128.0) Shininess = 128.0; glMaterialf(GL_FRONT, GL_SHININESS, Shininess); printf("Shininess = %g\n", Shininess); break; case ' ': ToggleAnimate(); break; case 27: exit(0); break; } glutPostRedisplay(); } } static void myinit(void) { /* Cylinder object */ { static GLfloat height = 100.0; static GLfloat radius = 40.0; static GLint slices = 24; /* pie slices around Z axis */ static GLint stacks = 10; /* subdivisions along length of cylinder */ static GLint rings = 4; /* rings in the end disks */ glEnable(GL_AUTO_NORMAL); glEnable(GL_NORMALIZE); GLUquadricObj *q = gluNewQuadric(); assert(q); gluQuadricTexture(q, GL_TRUE); CylinderObj = glGenLists(1); glNewList(CylinderObj, GL_COMPILE); glPushMatrix(); glTranslatef(0.0, 0.0, -0.5 * height); glMatrixMode(GL_TEXTURE); glLoadIdentity(); /*glScalef(8.0, 4.0, 2.0);*/ glMatrixMode(GL_MODELVIEW); /* cylinder */ gluQuadricNormals(q, GL_SMOOTH); gluQuadricTexture(q, GL_TRUE); gluCylinder(q, radius, radius, height, slices, stacks); /* end cap */ glMatrixMode(GL_TEXTURE); glLoadIdentity(); glScalef(3.0, 3.0, 1.0); glMatrixMode(GL_MODELVIEW); glTranslatef(0.0, 0.0, height); gluDisk(q, 0.0, radius, slices, rings); /* other end cap */ glTranslatef(0.0, 0.0, -height); gluQuadricOrientation(q, GLU_INSIDE); gluDisk(q, 0.0, radius, slices, rings); glPopMatrix(); glMatrixMode(GL_TEXTURE); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glEndList(); gluDeleteQuadric(q); } /* Teapot */ { TeapotObj = glGenLists(1); glNewList(TeapotObj, GL_COMPILE); glFrontFace(GL_CW); glutSolidTeapot(40.0); glFrontFace(GL_CCW); glEndList(); } /* show cylinder by default */ Object = CylinderObj; /* lighting */ glEnable(GL_LIGHTING); { GLfloat pos[4] = { 3, 3, 3, 1 }; glLightfv(GL_LIGHT0, GL_AMBIENT, Black); glLightfv(GL_LIGHT0, GL_DIFFUSE, White); glLightfv(GL_LIGHT0, GL_SPECULAR, White); glLightfv(GL_LIGHT0, GL_POSITION, pos); glEnable(GL_LIGHT0); glMaterialfv(GL_FRONT, GL_AMBIENT, Black); glMaterialf(GL_FRONT, GL_SHININESS, Shininess); glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1); } /* Base texture */ glGenTextures(1, &BaseTexture); glBindTexture(GL_TEXTURE_2D, BaseTexture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); if (!LoadRGBMipmaps(BASE_TEXTURE_FILE, GL_RGB)) { printf("Error: couldn't load texture image file %s\n", BASE_TEXTURE_FILE); exit(1); } /* Specular texture */ glGenTextures(1, &SpecularTexture); glBindTexture(GL_TEXTURE_2D, SpecularTexture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); #if 1 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); #else glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV); glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV); #endif if (!LoadRGBMipmaps(SPECULAR_TEXTURE_FILE, GL_RGB)) { printf("Error: couldn't load texture image file %s\n", SPECULAR_TEXTURE_FILE); exit(1); } /* misc */ glEnable(GL_CULL_FACE); glEnable(GL_TEXTURE_2D); glEnable(GL_DEPTH_TEST); glEnable(GL_NORMALIZE); } void creationMenus(void) { glutCreateMenu(ModeMenu); glutAddMenuEntry("Toggle Highlight",DO_SPEC_TEXTURE); glutAddMenuEntry("Toggle Object",OBJECT); glutAddMenuEntry("Toggle Animate",ANIMATE); glutAddMenuEntry("Quit",QUIT); glutAttachMenu(GLUT_RIGHT_BUTTON); } int main(int argc,char **argv) { glutInit(&argc,argv); glutInitWindowSize(250,250); glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH ); glutCreateWindow("Des objets mirroirs"); myinit(); creationMenus(); setParametresFrustumBasique(-30.0F,30.0F,-30.0,30.0F,150.0F,500.0F,0.0F,0.0F,-380.0F); setManipulateurDistance(380.0F); glutReshapeFunc(reshapeFrustumBasique); glutKeyboardFunc(key); glutSpecialFunc(specialBasique); glutMotionFunc(motionBasique); glutMouseFunc(sourisBasique); glutDisplayFunc(Display); glutIdleFunc(Idle); glutMainLoop(); return(0); }