blob: 54d8ad53630c5df4453754e2100e20cf5094aa73 [file] [log] [blame]
Brian Paul20cdbc01999-10-23 08:12:23 +00001/* $Id: gloss.c,v 1.2 1999/10/23 08:12:23 brianp Exp $ */
Brian Paulbb1119f1999-10-22 20:34:57 +00002
3/*
Brian Paul20cdbc01999-10-23 08:12:23 +00004 * Specular reflection demo. The specular highlight is modulated by
Brian Paulbb1119f1999-10-22 20:34:57 +00005 * a sphere-mapped texture. The result is a high-gloss surface.
6 * NOTE: you really need hardware acceleration for this.
Brian Paul20cdbc01999-10-23 08:12:23 +00007 * 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.
Brian Paulbb1119f1999-10-22 20:34:57 +000012 *
13 * Command line options:
14 * -info print GL implementation information
15 *
16 *
17 * Brian Paul October 22, 1999 This program is in the public domain.
18 */
19
20
21#include <assert.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <math.h>
25#include <GL/glut.h>
26
27#include "../util/readtex.c" /* I know, this is a hack. */
28
29#define SPECULAR_TEXTURE_FILE "../images/reflect.rgb"
30#define BASE_TEXTURE_FILE "../images/tile.rgb"
31
32/* Menu items */
33#define DO_SPEC_TEXTURE 1
34#define OBJECT 2
35#define ANIMATE 3
36#define QUIT 100
37
38static GLuint CylinderObj = 0;
39static GLuint TeapotObj = 0;
40static GLuint Object = 0;
41static GLboolean Animate = GL_TRUE;
42
43static GLfloat Xrot = 0.0, Yrot = 0.0, Zrot = 0.0;
44static GLfloat DXrot = 1.0, DYrot = 2.5;
45
46static GLfloat Black[4] = { 0, 0, 0, 0 };
47static GLfloat White[4] = { 1, 1, 1, 1 };
48static GLfloat Diffuse[4] = { .3, .3, 1.0, 1.0 }; /* blue */
49static GLfloat Shininess = 15;
50
51static GLuint BaseTexture, SpecularTexture;
52static GLboolean DoSpecTexture = GL_TRUE;
53
54/* performance info */
55static GLint T0 = 0;
56static GLint Frames = 0;
57
58
59
60
61static void Idle( void )
62{
63 if (Animate) {
64 Xrot += DXrot;
65 Yrot += DYrot;
66 glutPostRedisplay();
67 }
68}
69
70
71static void Display( void )
72{
73 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
74
75 glPushMatrix();
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);
79
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);
85 glMatrixMode(GL_TEXTURE);
86 glLoadIdentity();
87 glScalef(2.0, 2.0, 2.0);
88 glMatrixMode(GL_MODELVIEW);
89 glCallList(Object);
90 glMatrixMode(GL_TEXTURE);
91 glLoadIdentity();
92 glMatrixMode(GL_MODELVIEW);
93
94 /* Second pass: specular lighting with reflection texture */
95 glBlendFunc(GL_ONE, GL_ONE); /* add */
96 glEnable(GL_BLEND);
97 glDepthFunc(GL_LEQUAL);
98 glMaterialfv(GL_FRONT, GL_DIFFUSE, Black);
99 glMaterialfv(GL_FRONT, GL_SPECULAR, White);
100 if (DoSpecTexture) {
101 glBindTexture(GL_TEXTURE_2D, SpecularTexture);
102 glEnable(GL_TEXTURE_GEN_S);
103 glEnable(GL_TEXTURE_GEN_T);
104 }
105 else {
106 glDisable(GL_TEXTURE_2D);
107 }
108 glCallList(Object);
109 glDisable(GL_TEXTURE_GEN_S);
110 glDisable(GL_TEXTURE_GEN_T);
111 glDisable(GL_BLEND);
Brian Paulbb1119f1999-10-22 20:34:57 +0000112
113 glPopMatrix();
114
115 glutSwapBuffers();
116
117 if (Animate) {
118 GLint t = glutGet(GLUT_ELAPSED_TIME);
119 Frames++;
120 if (t - T0 >= 5000) {
121 GLfloat seconds = (t - T0) / 1000.0;
122 GLfloat fps = Frames / seconds;
123 printf("%d frames in %g seconds = %g FPS\n", Frames, seconds, fps);
124 T0 = t;
125 Frames = 0;
126 }
127 }
128}
129
130
131static void Reshape( int width, int height )
132{
133 GLfloat h = 30.0;
134 GLfloat w = h * width / height;
135 glViewport( 0, 0, width, height );
136 glMatrixMode( GL_PROJECTION );
137 glLoadIdentity();
138 glFrustum( -w, w, -h, h, 150.0, 500.0 );
139 glMatrixMode( GL_MODELVIEW );
140 glLoadIdentity();
141 glTranslatef( 0.0, 0.0, -380.0 );
142}
143
144
145static void ToggleAnimate(void)
146{
147 Animate = !Animate;
148 if (Animate) {
149 glutIdleFunc( Idle );
150 T0 = glutGet(GLUT_ELAPSED_TIME);
151 Frames = 0;
152 }
153 else {
154 glutIdleFunc( NULL );
155 }
156}
157
158
159static void ModeMenu(int entry)
160{
161 if (entry==ANIMATE) {
162 ToggleAnimate();
163 }
164 else if (entry==DO_SPEC_TEXTURE) {
165 DoSpecTexture = !DoSpecTexture;
166 }
167 else if (entry==OBJECT) {
168 if (Object == TeapotObj)
169 Object = CylinderObj;
170 else
171 Object = TeapotObj;
172 }
173 else if (entry==QUIT) {
174 exit(0);
175 }
176 glutPostRedisplay();
177}
178
179
180static void Key( unsigned char key, int x, int y )
181{
182 (void) x;
183 (void) y;
184 switch (key) {
185 case 's':
186 Shininess--;
187 if (Shininess < 0.0)
188 Shininess = 0.0;
189 glMaterialf(GL_FRONT, GL_SHININESS, Shininess);
190 printf("Shininess = %g\n", Shininess);
191 break;
192 case 'S':
193 Shininess++;
194 if (Shininess > 128.0)
195 Shininess = 128.0;
196 glMaterialf(GL_FRONT, GL_SHININESS, Shininess);
197 printf("Shininess = %g\n", Shininess);
198 break;
199 case ' ':
200 ToggleAnimate();
201 break;
202 case 27:
203 exit(0);
204 break;
205 }
206 glutPostRedisplay();
207}
208
209
210static void SpecialKey( int key, int x, int y )
211{
212 float step = 3.0;
213 (void) x;
214 (void) y;
215
216 switch (key) {
217 case GLUT_KEY_UP:
218 Xrot += step;
219 break;
220 case GLUT_KEY_DOWN:
221 Xrot -= step;
222 break;
223 case GLUT_KEY_LEFT:
224 Yrot += step;
225 break;
226 case GLUT_KEY_RIGHT:
227 Yrot -= step;
228 break;
229 }
230 glutPostRedisplay();
231}
232
233
234static void Init( int argc, char *argv[] )
235{
236 /* Cylinder object */
237 {
238 static GLfloat height = 100.0;
239 static GLfloat radius = 40.0;
240 GLUquadricObj *q = gluNewQuadric();
241 assert(q);
242 gluQuadricTexture(q, GL_TRUE);
243
244 CylinderObj = glGenLists(1);
245 glNewList(CylinderObj, GL_COMPILE);
246
247 glPushMatrix();
248 glTranslatef(0.0, 0.0, -0.5 * height);
249
250 /* cylinder */
251 gluQuadricNormals(q, GL_SMOOTH);
252 gluQuadricTexture(q, GL_TRUE);
253 gluCylinder(q, radius, radius, height, 24, 10);
254
255 /* end cap */
256 glTranslatef(0.0, 0.0, height);
257 gluDisk(q, 0.0, radius, 24, 1);
258
259 /* other end cap */
260 glTranslatef(0.0, 0.0, -height);
261 gluQuadricOrientation(q, GLU_INSIDE);
262 gluDisk(q, 0.0, radius, 24, 1);
263
264 glPopMatrix();
265 glEndList();
266 gluDeleteQuadric(q);
267 }
268
269 /* Teapot */
270 {
271 TeapotObj = glGenLists(1);
272 glNewList(TeapotObj, GL_COMPILE);
273
274 glFrontFace(GL_CW);
275 glutSolidTeapot(40.0);
276 glFrontFace(GL_CCW);
277
278 glEndList();
279 }
280
281 /* show cylinder by default */
282 Object = CylinderObj;
283
284
285 /* lighting */
286 glEnable(GL_LIGHTING);
287 {
288 GLfloat pos[4] = { 3, 3, 3, 1 };
289 glLightfv(GL_LIGHT0, GL_AMBIENT, Black);
290 glLightfv(GL_LIGHT0, GL_DIFFUSE, White);
291 glLightfv(GL_LIGHT0, GL_SPECULAR, White);
292 glLightfv(GL_LIGHT0, GL_POSITION, pos);
293 glEnable(GL_LIGHT0);
294 glMaterialfv(GL_FRONT, GL_AMBIENT, Black);
295 glMaterialf(GL_FRONT, GL_SHININESS, Shininess);
296 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
297 }
298
299 /* Base texture */
300 glGenTextures(1, &BaseTexture);
301 glBindTexture(GL_TEXTURE_2D, BaseTexture);
302 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
303 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
304 if (!LoadRGBMipmaps(BASE_TEXTURE_FILE, GL_RGB)) {
305 printf("Error: couldn't load texture image file %s\n", BASE_TEXTURE_FILE);
306 exit(1);
307 }
308
309 /* Specular texture */
310 glGenTextures(1, &SpecularTexture);
311 glBindTexture(GL_TEXTURE_2D, SpecularTexture);
312 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
313 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
314 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
315 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
316 if (!LoadRGBMipmaps(SPECULAR_TEXTURE_FILE, GL_RGB)) {
317 printf("Error: couldn't load texture image file %s\n", SPECULAR_TEXTURE_FILE);
318 exit(1);
319 }
320
321 /* misc */
322 glEnable(GL_CULL_FACE);
323 glEnable(GL_TEXTURE_2D);
324 glEnable(GL_DEPTH_TEST);
325 glEnable(GL_NORMALIZE);
326
327 if (argc > 1 && strcmp(argv[1], "-info")==0) {
328 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
329 printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
330 printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));
331 printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
332 }
333}
334
335
336int main( int argc, char *argv[] )
337{
338 glutInit( &argc, argv );
339 glutInitWindowSize( 500, 500 );
340
341 glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
342
343 glutCreateWindow(argv[0] );
344
345 Init(argc, argv);
346
347 glutReshapeFunc( Reshape );
348 glutKeyboardFunc( Key );
349 glutSpecialFunc( SpecialKey );
350 glutDisplayFunc( Display );
351 glutIdleFunc( Idle );
352
353 glutCreateMenu(ModeMenu);
354 glutAddMenuEntry("Toggle Highlight", DO_SPEC_TEXTURE);
355 glutAddMenuEntry("Toggle Object", OBJECT);
356 glutAddMenuEntry("Toggle Animate", ANIMATE);
357 glutAddMenuEntry("Quit", QUIT);
358 glutAttachMenu(GLUT_RIGHT_BUTTON);
359
360 glutMainLoop();
361 return 0;
362}