1 2/* 3 * GLUT demonstration of texturing with specular highlights. 4 * 5 * When drawing a lit, textured surface one usually wants the specular 6 * highlight to override the texture colors. However, OpenGL applies 7 * texturing after lighting so the specular highlight is modulated by 8 * the texture. 9 * 10 * The solution here shown here is a two-pass algorithm: 11 * 1. Draw the textured surface without specular lighting. 12 * 2. Enable blending to add the next pass: 13 * 3. Redraw the surface with a matte white material and only the 14 * specular components of light sources enabled. 15 * 16 * Brian Paul February 1997 17 */ 18 19#include <stdio.h> 20#include <stdlib.h> 21#include <math.h> 22#include "glut_wrap.h" 23 24 25static GLUquadricObj *Quadric; 26static GLuint Sphere; 27static GLfloat LightPos[4] = {10.0, 10.0, 10.0, 1.0}; 28static GLfloat Delta = 20.0; 29static GLint Mode = 4; 30 31/*static GLfloat Blue[4] = {0.0, 0.0, 1.0, 1.0};*/ 32/*static GLfloat Gray[4] = {0.5, 0.5, 0.5, 1.0};*/ 33static GLfloat Black[4] = {0.0, 0.0, 0.0, 1.0}; 34static GLfloat White[4] = {1.0, 1.0, 1.0, 1.0}; 35 36static GLboolean smooth = 1; 37 38static void 39Idle(void) 40{ 41 static double t0 = -1.; 42 double dt, t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;; 43 if (t0 < 0.0) 44 t0 = t; 45 dt = t - t0; 46 t0 = t; 47 LightPos[0] += Delta * dt; 48 if (LightPos[0]>15.0 || LightPos[0]<-15.0) 49 Delta = -Delta; 50 51 glutPostRedisplay(); 52} 53 54 55static void Display( void ) 56{ 57 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); 58 59 glLightfv(GL_LIGHT0, GL_POSITION, LightPos); 60 61 glPushMatrix(); 62 glRotatef(90.0, 1.0, 0.0, 0.0); 63 64 if (Mode==0) { 65 /* Typical method: diffuse + specular + texture */ 66 glEnable(GL_TEXTURE_2D); 67 glLightfv(GL_LIGHT0, GL_DIFFUSE, White); /* enable diffuse */ 68 glLightfv(GL_LIGHT0, GL_SPECULAR, White); /* enable specular */ 69#ifdef GL_VERSION_1_2 70 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR); 71#endif 72 glCallList(Sphere); 73 } 74 else if (Mode==1) { 75 /* just specular highlight */ 76 glDisable(GL_TEXTURE_2D); 77 glLightfv(GL_LIGHT0, GL_DIFFUSE, Black); /* disable diffuse */ 78 glLightfv(GL_LIGHT0, GL_SPECULAR, White); /* enable specular */ 79#ifdef GL_VERSION_1_2 80 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR); 81#endif 82 glCallList(Sphere); 83 } 84 else if (Mode==2) { 85 /* diffuse textured */ 86 glEnable(GL_TEXTURE_2D); 87 glLightfv(GL_LIGHT0, GL_DIFFUSE, White); /* enable diffuse */ 88 glLightfv(GL_LIGHT0, GL_SPECULAR, Black); /* disable specular */ 89#ifdef GL_VERSION_1_2 90 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR); 91#endif 92 glCallList(Sphere); 93 } 94 else if (Mode==3) { 95 /* 2-pass: diffuse textured then add specular highlight*/ 96 glEnable(GL_TEXTURE_2D); 97 glLightfv(GL_LIGHT0, GL_DIFFUSE, White); /* enable diffuse */ 98 glLightfv(GL_LIGHT0, GL_SPECULAR, Black); /* disable specular */ 99#ifdef GL_VERSION_1_2 100 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR); 101#endif 102 glCallList(Sphere); 103 /* specular highlight */ 104 glDepthFunc(GL_EQUAL); /* redraw same pixels */ 105 glDisable(GL_TEXTURE_2D); 106 glEnable(GL_BLEND); /* add */ 107 glLightfv(GL_LIGHT0, GL_DIFFUSE, Black); /* disable diffuse */ 108 glLightfv(GL_LIGHT0, GL_SPECULAR, White); /* enable specular */ 109 glCallList(Sphere); 110 glDepthFunc(GL_LESS); 111 glDisable(GL_BLEND); 112 } 113 else if (Mode==4) { 114 /* OpenGL 1.2's separate diffuse and specular color */ 115 glEnable(GL_TEXTURE_2D); 116 glLightfv(GL_LIGHT0, GL_DIFFUSE, White); /* enable diffuse */ 117 glLightfv(GL_LIGHT0, GL_SPECULAR, White); /* enable specular */ 118#ifdef GL_VERSION_1_2 119 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); 120#endif 121 glCallList(Sphere); 122 } 123 124 glPopMatrix(); 125 126 glutSwapBuffers(); 127} 128 129 130static void Reshape( int width, int height ) 131{ 132 glViewport( 0, 0, width, height ); 133 glMatrixMode( GL_PROJECTION ); 134 glLoadIdentity(); 135 glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 25.0 ); 136 glMatrixMode( GL_MODELVIEW ); 137 glLoadIdentity(); 138 glTranslatef( 0.0, 0.0, -12.0 ); 139} 140 141 142static void Key( unsigned char key, int x, int y ) 143{ 144 (void) x; 145 (void) y; 146 switch (key) { 147 case 27: 148 exit(0); 149 break; 150 case 's': 151 smooth = !smooth; 152 if (smooth) 153 glShadeModel(GL_SMOOTH); 154 else 155 glShadeModel(GL_FLAT); 156 break; 157 } 158 glutPostRedisplay(); 159} 160 161 162static void SpecialKey( int key, int x, int y ) 163{ 164 (void) x; 165 (void) y; 166 switch (key) { 167 case GLUT_KEY_UP: 168 break; 169 case GLUT_KEY_DOWN: 170 break; 171 } 172 glutPostRedisplay(); 173} 174 175 176static void Init( void ) 177{ 178 int i, j; 179 GLubyte texImage[64][64][3]; 180 181 glEnable(GL_LIGHTING); 182 glEnable(GL_LIGHT0); 183 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0); 184 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, Black); 185 186 glShadeModel(GL_SMOOTH); 187 188 glMaterialfv(GL_FRONT, GL_DIFFUSE, White); 189 glMaterialfv(GL_FRONT, GL_SPECULAR, White); 190 glMaterialf(GL_FRONT, GL_SHININESS, 20.0); 191 192 /* Actually, these are set again later */ 193 glLightfv(GL_LIGHT0, GL_DIFFUSE, White); 194 glLightfv(GL_LIGHT0, GL_SPECULAR, White); 195 196 Quadric = gluNewQuadric(); 197 gluQuadricTexture( Quadric, GL_TRUE ); 198 199 Sphere= glGenLists(1); 200 glNewList( Sphere, GL_COMPILE ); 201 gluSphere( Quadric, 1.0, 24, 24 ); 202 glEndList(); 203 204 glEnable(GL_DEPTH_TEST); 205 glEnable(GL_CULL_FACE); 206 207 for (i=0;i<64;i++) { 208 for (j=0;j<64;j++) { 209 int k = ((i>>3)&1) ^ ((j>>3)&1); 210 texImage[i][j][0] = 255*k; 211 texImage[i][j][1] = 255*(1-k); 212 texImage[i][j][2] = 0; 213 } 214 } 215 216 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 217 glTexImage2D( GL_TEXTURE_2D, 218 0, 219 3, 220 64, 64, 221 0, 222 GL_RGB, GL_UNSIGNED_BYTE, 223 texImage ); 224 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 225 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 226 glEnable(GL_TEXTURE_2D); 227 228 glBlendFunc(GL_ONE, GL_ONE); 229} 230 231 232static void ModeMenu(int entry) 233{ 234 if (entry==99) 235 exit(0); 236 Mode = entry; 237} 238 239 240int main( int argc, char *argv[] ) 241{ 242 glutInitWindowSize( 300, 300 ); 243 glutInit( &argc, argv ); 244 glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ); 245 glutCreateWindow( "spectex" ); 246 247 Init(); 248 249 glutReshapeFunc( Reshape ); 250 glutKeyboardFunc( Key ); 251 glutSpecialFunc( SpecialKey ); 252 glutDisplayFunc( Display ); 253 glutIdleFunc( Idle ); 254 255 glutCreateMenu( ModeMenu ); 256 glutAddMenuEntry("1-pass lighting + texturing", 0); 257 glutAddMenuEntry("specular lighting", 1); 258 glutAddMenuEntry("diffuse lighting + texturing", 2); 259 glutAddMenuEntry("2-pass lighting + texturing", 3); 260#ifdef GL_VERSION_1_2 261 glutAddMenuEntry("OpenGL 1.2 separate specular", 4); 262#endif 263 glutAddMenuEntry("Quit", 99); 264 glutAttachMenu(GLUT_RIGHT_BUTTON); 265 266 glutMainLoop(); 267 return 0; 268} 269