1 /* $Id: gloss.c,v 1.7 2002/11/28 15:51:55 brianp Exp $ */
4 * Specular reflection demo. The specular highlight is modulated by
5 * a sphere-mapped texture. The result is a high-gloss surface.
6 * NOTE: you really need hardware acceleration for this.
7 * Also note, this technique can't be implemented with multi-texture
8 * and separate specular color interpolation because there's no way
9 * to indicate that the second texture unit (the reflection map)
10 * should modulate the specular color and not the base color.
11 * A future multi-texture extension could fix that.
13 * Command line options:
14 * -info print GL implementation information
17 * Brian Paul October 22, 1999 This program is in the public domain.
27 #include "readtex.c" /* I know, this is a hack. */
29 #define SPECULAR_TEXTURE_FILE "../images/reflect.rgb"
30 #define BASE_TEXTURE_FILE "../images/tile.rgb"
33 #define DO_SPEC_TEXTURE 1
38 static GLuint CylinderObj
= 0;
39 static GLuint TeapotObj
= 0;
40 static GLuint Object
= 0;
41 static GLboolean Animate
= GL_TRUE
;
43 static GLfloat Xrot
= 0.0, Yrot
= 0.0, Zrot
= 0.0;
44 static GLfloat DXrot
= 1.0, DYrot
= 2.5;
46 static GLfloat Black
[4] = { 0, 0, 0, 0 };
47 static GLfloat White
[4] = { 1, 1, 1, 1 };
48 static GLfloat Diffuse
[4] = { .3, .3, 1.0, 1.0 }; /* blue */
49 static GLfloat Shininess
= 6;
51 static GLuint BaseTexture
, SpecularTexture
;
52 static GLboolean DoSpecTexture
= GL_TRUE
;
54 /* performance info */
56 static GLint Frames
= 0;
61 static void Idle( void )
71 static void Display( void )
73 glClear( GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
76 glRotatef(Xrot
, 1.0, 0.0, 0.0);
77 glRotatef(Yrot
, 0.0, 1.0, 0.0);
78 glRotatef(Zrot
, 0.0, 0.0, 1.0);
80 /* First pass: diffuse lighting with base texture */
81 glMaterialfv(GL_FRONT
, GL_DIFFUSE
, Diffuse
);
82 glMaterialfv(GL_FRONT
, GL_SPECULAR
, Black
);
83 glEnable(GL_TEXTURE_2D
);
84 glBindTexture(GL_TEXTURE_2D
, BaseTexture
);
87 /* Second pass: specular lighting with reflection texture */
88 glEnable(GL_POLYGON_OFFSET_FILL
);
89 glBlendFunc(GL_ONE
, GL_ONE
); /* add */
91 glMaterialfv(GL_FRONT
, GL_DIFFUSE
, Black
);
92 glMaterialfv(GL_FRONT
, GL_SPECULAR
, White
);
94 glBindTexture(GL_TEXTURE_2D
, SpecularTexture
);
95 glEnable(GL_TEXTURE_GEN_S
);
96 glEnable(GL_TEXTURE_GEN_T
);
99 glDisable(GL_TEXTURE_2D
);
102 glDisable(GL_TEXTURE_GEN_S
);
103 glDisable(GL_TEXTURE_GEN_T
);
105 glDisable(GL_POLYGON_OFFSET_FILL
);
112 GLint t
= glutGet(GLUT_ELAPSED_TIME
);
114 if (t
- T0
>= 5000) {
115 GLfloat seconds
= (t
- T0
) / 1000.0;
116 GLfloat fps
= Frames
/ seconds
;
117 printf("%d frames in %g seconds = %g FPS\n", Frames
, seconds
, fps
);
125 static void Reshape( int width
, int height
)
128 GLfloat w
= h
* width
/ height
;
129 glViewport( 0, 0, width
, height
);
130 glMatrixMode( GL_PROJECTION
);
132 glFrustum( -w
, w
, -h
, h
, 150.0, 500.0 );
133 glMatrixMode( GL_MODELVIEW
);
135 glTranslatef( 0.0, 0.0, -380.0 );
139 static void ToggleAnimate(void)
143 glutIdleFunc( Idle
);
144 T0
= glutGet(GLUT_ELAPSED_TIME
);
148 glutIdleFunc( NULL
);
153 static void ModeMenu(int entry
)
155 if (entry
==ANIMATE
) {
158 else if (entry
==DO_SPEC_TEXTURE
) {
159 DoSpecTexture
= !DoSpecTexture
;
161 else if (entry
==OBJECT
) {
162 if (Object
== TeapotObj
)
163 Object
= CylinderObj
;
167 else if (entry
==QUIT
) {
174 static void Key( unsigned char key
, int x
, int y
)
183 glMaterialf(GL_FRONT
, GL_SHININESS
, Shininess
);
184 printf("Shininess = %g\n", Shininess
);
188 if (Shininess
> 128.0)
190 glMaterialf(GL_FRONT
, GL_SHININESS
, Shininess
);
191 printf("Shininess = %g\n", Shininess
);
204 static void SpecialKey( int key
, int x
, int y
)
228 static void Init( int argc
, char *argv
[] )
230 /* Cylinder object */
232 static GLfloat height
= 100.0;
233 static GLfloat radius
= 40.0;
234 static GLint slices
= 24; /* pie slices around Z axis */
235 static GLint stacks
= 10; /* subdivisions along length of cylinder */
236 static GLint rings
= 4; /* rings in the end disks */
237 GLUquadricObj
*q
= gluNewQuadric();
239 gluQuadricTexture(q
, GL_TRUE
);
241 CylinderObj
= glGenLists(1);
242 glNewList(CylinderObj
, GL_COMPILE
);
245 glTranslatef(0.0, 0.0, -0.5 * height
);
247 glMatrixMode(GL_TEXTURE
);
249 /*glScalef(8.0, 4.0, 2.0);*/
250 glMatrixMode(GL_MODELVIEW
);
253 gluQuadricNormals(q
, GL_SMOOTH
);
254 gluQuadricTexture(q
, GL_TRUE
);
255 gluCylinder(q
, radius
, radius
, height
, slices
, stacks
);
258 glMatrixMode(GL_TEXTURE
);
260 glScalef(3.0, 3.0, 1.0);
261 glMatrixMode(GL_MODELVIEW
);
263 glTranslatef(0.0, 0.0, height
);
264 gluDisk(q
, 0.0, radius
, slices
, rings
);
267 glTranslatef(0.0, 0.0, -height
);
268 gluQuadricOrientation(q
, GLU_INSIDE
);
269 gluDisk(q
, 0.0, radius
, slices
, rings
);
273 glMatrixMode(GL_TEXTURE
);
275 glMatrixMode(GL_MODELVIEW
);
283 TeapotObj
= glGenLists(1);
284 glNewList(TeapotObj
, GL_COMPILE
);
287 glutSolidTeapot(40.0);
293 /* show cylinder by default */
294 Object
= CylinderObj
;
298 glEnable(GL_LIGHTING
);
300 GLfloat pos
[4] = { 3, 3, 3, 1 };
301 glLightfv(GL_LIGHT0
, GL_AMBIENT
, Black
);
302 glLightfv(GL_LIGHT0
, GL_DIFFUSE
, White
);
303 glLightfv(GL_LIGHT0
, GL_SPECULAR
, White
);
304 glLightfv(GL_LIGHT0
, GL_POSITION
, pos
);
306 glMaterialfv(GL_FRONT
, GL_AMBIENT
, Black
);
307 glMaterialf(GL_FRONT
, GL_SHININESS
, Shininess
);
308 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER
, 1);
312 glGenTextures(1, &BaseTexture
);
313 glBindTexture(GL_TEXTURE_2D
, BaseTexture
);
314 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
315 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
316 if (!LoadRGBMipmaps(BASE_TEXTURE_FILE
, GL_RGB
)) {
317 printf("Error: couldn't load texture image file %s\n", BASE_TEXTURE_FILE
);
321 /* Specular texture */
322 glGenTextures(1, &SpecularTexture
);
323 glBindTexture(GL_TEXTURE_2D
, SpecularTexture
);
324 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
325 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
327 glTexGeni(GL_S
, GL_TEXTURE_GEN_MODE
, GL_SPHERE_MAP
);
328 glTexGeni(GL_T
, GL_TEXTURE_GEN_MODE
, GL_SPHERE_MAP
);
330 glTexGeni(GL_S
, GL_TEXTURE_GEN_MODE
, GL_NORMAL_MAP_NV
);
331 glTexGeni(GL_T
, GL_TEXTURE_GEN_MODE
, GL_NORMAL_MAP_NV
);
332 glTexGeni(GL_R
, GL_TEXTURE_GEN_MODE
, GL_NORMAL_MAP_NV
);
334 if (!LoadRGBMipmaps(SPECULAR_TEXTURE_FILE
, GL_RGB
)) {
335 printf("Error: couldn't load texture image file %s\n", SPECULAR_TEXTURE_FILE
);
340 glEnable(GL_CULL_FACE
);
341 glEnable(GL_TEXTURE_2D
);
342 glEnable(GL_DEPTH_TEST
);
343 glEnable(GL_NORMALIZE
);
345 glPolygonOffset( -1, -1 );
347 if (argc
> 1 && strcmp(argv
[1], "-info")==0) {
348 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER
));
349 printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION
));
350 printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR
));
351 printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS
));
356 int main( int argc
, char *argv
[] )
358 glutInit( &argc
, argv
);
359 glutInitWindowSize( 500, 500 );
361 glutInitDisplayMode( GLUT_RGB
| GLUT_DOUBLE
| GLUT_DEPTH
);
363 glutCreateWindow(argv
[0] );
367 glutReshapeFunc( Reshape
);
368 glutKeyboardFunc( Key
);
369 glutSpecialFunc( SpecialKey
);
370 glutDisplayFunc( Display
);
371 glutIdleFunc( Idle
);
373 glutCreateMenu(ModeMenu
);
374 glutAddMenuEntry("Toggle Highlight", DO_SPEC_TEXTURE
);
375 glutAddMenuEntry("Toggle Object", OBJECT
);
376 glutAddMenuEntry("Toggle Animate", ANIMATE
);
377 glutAddMenuEntry("Quit", QUIT
);
378 glutAttachMenu(GLUT_RIGHT_BUTTON
);