3 * Specular reflection demo. The specular highlight is modulated by
4 * a sphere-mapped texture. The result is a high-gloss surface.
5 * NOTE: you really need hardware acceleration for this.
6 * Also note, this technique can't be implemented with multi-texture
7 * and separate specular color interpolation because there's no way
8 * to indicate that the second texture unit (the reflection map)
9 * should modulate the specular color and not the base color.
10 * A future multi-texture extension could fix that.
12 * Command line options:
13 * -info print GL implementation information
16 * Brian Paul October 22, 1999 This program is in the public domain.
26 #include "readtex.c" /* I know, this is a hack. */
28 #define SPECULAR_TEXTURE_FILE "../images/reflect.rgb"
29 #define BASE_TEXTURE_FILE "../images/tile.rgb"
32 #define DO_SPEC_TEXTURE 1
37 static GLuint CylinderObj
= 0;
38 static GLuint TeapotObj
= 0;
39 static GLuint Object
= 0;
40 static GLboolean Animate
= GL_TRUE
;
42 static GLfloat Xrot
= 0.0, Yrot
= 0.0, Zrot
= 0.0;
43 static GLfloat DXrot
= 1.0, DYrot
= 2.5;
45 static GLfloat Black
[4] = { 0, 0, 0, 0 };
46 static GLfloat White
[4] = { 1, 1, 1, 1 };
47 static GLfloat Diffuse
[4] = { .3, .3, 1.0, 1.0 }; /* blue */
48 static GLfloat Shininess
= 6;
50 static GLuint BaseTexture
, SpecularTexture
;
51 static GLboolean DoSpecTexture
= GL_TRUE
;
53 /* performance info */
55 static GLint Frames
= 0;
60 static void Idle( void )
70 static void Display( void )
72 glClear( GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
75 glRotatef(Xrot
, 1.0, 0.0, 0.0);
76 glRotatef(Yrot
, 0.0, 1.0, 0.0);
77 glRotatef(Zrot
, 0.0, 0.0, 1.0);
79 /* First pass: diffuse lighting with base texture */
80 glMaterialfv(GL_FRONT
, GL_DIFFUSE
, Diffuse
);
81 glMaterialfv(GL_FRONT
, GL_SPECULAR
, Black
);
82 glEnable(GL_TEXTURE_2D
);
83 glBindTexture(GL_TEXTURE_2D
, BaseTexture
);
86 /* Second pass: specular lighting with reflection texture */
87 glEnable(GL_POLYGON_OFFSET_FILL
);
88 glBlendFunc(GL_ONE
, GL_ONE
); /* add */
90 glMaterialfv(GL_FRONT
, GL_DIFFUSE
, Black
);
91 glMaterialfv(GL_FRONT
, GL_SPECULAR
, White
);
93 glBindTexture(GL_TEXTURE_2D
, SpecularTexture
);
94 glEnable(GL_TEXTURE_GEN_S
);
95 glEnable(GL_TEXTURE_GEN_T
);
98 glDisable(GL_TEXTURE_2D
);
101 glDisable(GL_TEXTURE_GEN_S
);
102 glDisable(GL_TEXTURE_GEN_T
);
104 glDisable(GL_POLYGON_OFFSET_FILL
);
111 GLint t
= glutGet(GLUT_ELAPSED_TIME
);
113 if (t
- T0
>= 5000) {
114 GLfloat seconds
= (t
- T0
) / 1000.0;
115 GLfloat fps
= Frames
/ seconds
;
116 printf("%d frames in %g seconds = %g FPS\n", Frames
, seconds
, fps
);
124 static void Reshape( int width
, int height
)
127 GLfloat w
= h
* width
/ height
;
128 glViewport( 0, 0, width
, height
);
129 glMatrixMode( GL_PROJECTION
);
131 glFrustum( -w
, w
, -h
, h
, 150.0, 500.0 );
132 glMatrixMode( GL_MODELVIEW
);
134 glTranslatef( 0.0, 0.0, -380.0 );
138 static void ToggleAnimate(void)
142 glutIdleFunc( Idle
);
143 T0
= glutGet(GLUT_ELAPSED_TIME
);
147 glutIdleFunc( NULL
);
152 static void ModeMenu(int entry
)
154 if (entry
==ANIMATE
) {
157 else if (entry
==DO_SPEC_TEXTURE
) {
158 DoSpecTexture
= !DoSpecTexture
;
160 else if (entry
==OBJECT
) {
161 if (Object
== TeapotObj
)
162 Object
= CylinderObj
;
166 else if (entry
==QUIT
) {
173 static void Key( unsigned char key
, int x
, int y
)
182 glMaterialf(GL_FRONT
, GL_SHININESS
, Shininess
);
183 printf("Shininess = %g\n", Shininess
);
187 if (Shininess
> 128.0)
189 glMaterialf(GL_FRONT
, GL_SHININESS
, Shininess
);
190 printf("Shininess = %g\n", Shininess
);
203 static void SpecialKey( int key
, int x
, int y
)
227 static void Init( int argc
, char *argv
[] )
229 /* Cylinder object */
231 static GLfloat height
= 100.0;
232 static GLfloat radius
= 40.0;
233 static GLint slices
= 24; /* pie slices around Z axis */
234 static GLint stacks
= 10; /* subdivisions along length of cylinder */
235 static GLint rings
= 4; /* rings in the end disks */
236 GLUquadricObj
*q
= gluNewQuadric();
238 gluQuadricTexture(q
, GL_TRUE
);
240 CylinderObj
= glGenLists(1);
241 glNewList(CylinderObj
, GL_COMPILE
);
244 glTranslatef(0.0, 0.0, -0.5 * height
);
246 glMatrixMode(GL_TEXTURE
);
248 /*glScalef(8.0, 4.0, 2.0);*/
249 glMatrixMode(GL_MODELVIEW
);
252 gluQuadricNormals(q
, GL_SMOOTH
);
253 gluQuadricTexture(q
, GL_TRUE
);
254 gluCylinder(q
, radius
, radius
, height
, slices
, stacks
);
257 glMatrixMode(GL_TEXTURE
);
259 glScalef(3.0, 3.0, 1.0);
260 glMatrixMode(GL_MODELVIEW
);
262 glTranslatef(0.0, 0.0, height
);
263 gluDisk(q
, 0.0, radius
, slices
, rings
);
266 glTranslatef(0.0, 0.0, -height
);
267 gluQuadricOrientation(q
, GLU_INSIDE
);
268 gluDisk(q
, 0.0, radius
, slices
, rings
);
272 glMatrixMode(GL_TEXTURE
);
274 glMatrixMode(GL_MODELVIEW
);
282 TeapotObj
= glGenLists(1);
283 glNewList(TeapotObj
, GL_COMPILE
);
286 glutSolidTeapot(40.0);
292 /* show cylinder by default */
293 Object
= CylinderObj
;
297 glEnable(GL_LIGHTING
);
299 GLfloat pos
[4] = { 3, 3, 3, 1 };
300 glLightfv(GL_LIGHT0
, GL_AMBIENT
, Black
);
301 glLightfv(GL_LIGHT0
, GL_DIFFUSE
, White
);
302 glLightfv(GL_LIGHT0
, GL_SPECULAR
, White
);
303 glLightfv(GL_LIGHT0
, GL_POSITION
, pos
);
305 glMaterialfv(GL_FRONT
, GL_AMBIENT
, Black
);
306 glMaterialf(GL_FRONT
, GL_SHININESS
, Shininess
);
307 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER
, 1);
311 glGenTextures(1, &BaseTexture
);
312 glBindTexture(GL_TEXTURE_2D
, BaseTexture
);
313 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
314 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
315 if (!LoadRGBMipmaps(BASE_TEXTURE_FILE
, GL_RGB
)) {
316 printf("Error: couldn't load texture image file %s\n", BASE_TEXTURE_FILE
);
320 /* Specular texture */
321 glGenTextures(1, &SpecularTexture
);
322 glBindTexture(GL_TEXTURE_2D
, SpecularTexture
);
323 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
324 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
326 glTexGeni(GL_S
, GL_TEXTURE_GEN_MODE
, GL_SPHERE_MAP
);
327 glTexGeni(GL_T
, GL_TEXTURE_GEN_MODE
, GL_SPHERE_MAP
);
329 glTexGeni(GL_S
, GL_TEXTURE_GEN_MODE
, GL_NORMAL_MAP_NV
);
330 glTexGeni(GL_T
, GL_TEXTURE_GEN_MODE
, GL_NORMAL_MAP_NV
);
331 glTexGeni(GL_R
, GL_TEXTURE_GEN_MODE
, GL_NORMAL_MAP_NV
);
333 if (!LoadRGBMipmaps(SPECULAR_TEXTURE_FILE
, GL_RGB
)) {
334 printf("Error: couldn't load texture image file %s\n", SPECULAR_TEXTURE_FILE
);
339 glEnable(GL_CULL_FACE
);
340 glEnable(GL_TEXTURE_2D
);
341 glEnable(GL_DEPTH_TEST
);
342 glEnable(GL_NORMALIZE
);
344 glPolygonOffset( -1, -1 );
346 if (argc
> 1 && strcmp(argv
[1], "-info")==0) {
347 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER
));
348 printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION
));
349 printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR
));
350 printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS
));
355 int main( int argc
, char *argv
[] )
357 glutInit( &argc
, argv
);
358 glutInitWindowSize( 500, 500 );
360 glutInitDisplayMode( GLUT_RGB
| GLUT_DOUBLE
| GLUT_DEPTH
);
362 glutCreateWindow(argv
[0] );
366 glutReshapeFunc( Reshape
);
367 glutKeyboardFunc( Key
);
368 glutSpecialFunc( SpecialKey
);
369 glutDisplayFunc( Display
);
370 glutIdleFunc( Idle
);
372 glutCreateMenu(ModeMenu
);
373 glutAddMenuEntry("Toggle Highlight", DO_SPEC_TEXTURE
);
374 glutAddMenuEntry("Toggle Object", OBJECT
);
375 glutAddMenuEntry("Toggle Animate", ANIMATE
);
376 glutAddMenuEntry("Quit", QUIT
);
377 glutAttachMenu(GLUT_RIGHT_BUTTON
);