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