WIP - port to Mali EGL
[mesa-demos/mali.git] / src / demos / gloss.c
bloba198a6367e3d920a8d4c1e803f25238fe3bb1d4a
2 /*
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.
20 #include <assert.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <math.h>
24 #include <string.h>
25 #include <GL/glew.h>
26 #include "glut_wrap.h"
28 #include "readtex.h"
29 #include "trackball.h"
32 #define SPECULAR_TEXTURE_FILE DEMOS_DATA_DIR "reflect.rgb"
33 #define BASE_TEXTURE_FILE DEMOS_DATA_DIR "tile.rgb"
35 /* Menu items */
36 #define DO_SPEC_TEXTURE 1
37 #define OBJECT 2
38 #define ANIMATE 3
39 #define QUIT 100
41 /* for convolution */
42 #define FILTER_SIZE 7
44 static GLint Win;
45 static GLint WinWidth = 500, WinHeight = 500;
46 static GLuint CylinderObj = 0;
47 static GLuint TeapotObj = 0;
48 static GLuint Object = 0;
49 static GLboolean Animate = GL_TRUE;
51 static float CurQuat[4] = { 0, 0, 0, 1 };
53 static GLfloat Black[4] = { 0, 0, 0, 0 };
54 static GLfloat White[4] = { 1, 1, 1, 1 };
55 static GLfloat Diffuse[4] = { .3, .3, 1.0, 1.0 }; /* blue */
56 static GLfloat Shininess = 6;
58 static GLuint BaseTexture, SpecularTexture;
59 static GLboolean DoSpecTexture = GL_TRUE;
61 static GLboolean ButtonDown = GL_FALSE;
62 static GLint ButtonX, ButtonY;
65 /* performance info */
66 static GLint T0 = 0;
67 static GLint Frames = 0;
70 static void Idle( void )
72 static const float yAxis[3] = {0, 1, 0};
73 static double t0 = -1.;
74 float quat[4];
75 double dt, t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
76 if (t0 < 0.0)
77 t0 = t;
78 dt = t - t0;
79 t0 = t;
81 axis_to_quat(yAxis, 2.0 * dt, quat);
82 add_quats(quat, CurQuat, CurQuat);
84 glutPostRedisplay();
88 static void Display( void )
90 GLfloat rot[4][4];
92 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
94 glPushMatrix();
95 build_rotmatrix(rot, CurQuat);
96 glMultMatrixf(&rot[0][0]);
98 /* First pass: diffuse lighting with base texture */
99 glMaterialfv(GL_FRONT, GL_DIFFUSE, Diffuse);
100 glMaterialfv(GL_FRONT, GL_SPECULAR, Black);
101 glEnable(GL_TEXTURE_2D);
102 glBindTexture(GL_TEXTURE_2D, BaseTexture);
103 glCallList(Object);
105 /* Second pass: specular lighting with reflection texture */
106 glEnable(GL_POLYGON_OFFSET_FILL);
107 glBlendFunc(GL_ONE, GL_ONE); /* add */
108 glEnable(GL_BLEND);
109 glMaterialfv(GL_FRONT, GL_DIFFUSE, Black);
110 glMaterialfv(GL_FRONT, GL_SPECULAR, White);
111 if (DoSpecTexture) {
112 glBindTexture(GL_TEXTURE_2D, SpecularTexture);
113 glEnable(GL_TEXTURE_GEN_S);
114 glEnable(GL_TEXTURE_GEN_T);
116 else {
117 glDisable(GL_TEXTURE_2D);
119 glCallList(Object);
120 glDisable(GL_TEXTURE_GEN_S);
121 glDisable(GL_TEXTURE_GEN_T);
122 glDisable(GL_BLEND);
123 glDisable(GL_POLYGON_OFFSET_FILL);
125 glPopMatrix();
127 glutSwapBuffers();
129 if (Animate) {
130 GLint t = glutGet(GLUT_ELAPSED_TIME);
131 Frames++;
132 if (t - T0 >= 5000) {
133 GLfloat seconds = (t - T0) / 1000.0;
134 GLfloat fps = Frames / seconds;
135 printf("%d frames in %g seconds = %g FPS\n", Frames, seconds, fps);
136 fflush(stdout);
137 T0 = t;
138 Frames = 0;
144 static void Reshape( int width, int height )
146 GLfloat h = 30.0;
147 GLfloat w = h * width / height;
148 WinWidth = width;
149 WinHeight = height;
150 glViewport( 0, 0, width, height );
151 glMatrixMode( GL_PROJECTION );
152 glLoadIdentity();
153 glFrustum( -w, w, -h, h, 150.0, 500.0 );
154 glMatrixMode( GL_MODELVIEW );
155 glLoadIdentity();
156 glTranslatef( 0.0, 0.0, -380.0 );
160 static void ToggleAnimate(void)
162 Animate = !Animate;
163 if (Animate) {
164 glutIdleFunc( Idle );
165 T0 = glutGet(GLUT_ELAPSED_TIME);
166 Frames = 0;
168 else {
169 glutIdleFunc( NULL );
174 static void ModeMenu(int entry)
176 if (entry==ANIMATE) {
177 ToggleAnimate();
179 else if (entry==DO_SPEC_TEXTURE) {
180 DoSpecTexture = !DoSpecTexture;
182 else if (entry==OBJECT) {
183 if (Object == TeapotObj)
184 Object = CylinderObj;
185 else
186 Object = TeapotObj;
188 else if (entry==QUIT) {
189 exit(0);
191 glutPostRedisplay();
195 static void Key( unsigned char key, int x, int y )
197 (void) x;
198 (void) y;
199 switch (key) {
200 case 's':
201 Shininess--;
202 if (Shininess < 0.0)
203 Shininess = 0.0;
204 glMaterialf(GL_FRONT, GL_SHININESS, Shininess);
205 printf("Shininess = %g\n", Shininess);
206 break;
207 case 'S':
208 Shininess++;
209 if (Shininess > 128.0)
210 Shininess = 128.0;
211 glMaterialf(GL_FRONT, GL_SHININESS, Shininess);
212 printf("Shininess = %g\n", Shininess);
213 break;
214 case 'a':
215 case ' ':
216 ToggleAnimate();
217 break;
218 case 'n':
219 Idle();
220 break;
221 case 27:
222 glutDestroyWindow(Win);
223 exit(0);
224 break;
226 glutPostRedisplay();
230 static void
231 MouseMotion(int x, int y)
233 if (ButtonDown) {
234 float x0 = (2.0 * ButtonX - WinWidth) / WinWidth;
235 float y0 = (WinHeight - 2.0 * ButtonY) / WinHeight;
236 float x1 = (2.0 * x - WinWidth) / WinWidth;
237 float y1 = (WinHeight - 2.0 * y) / WinHeight;
238 float q[4];
240 trackball(q, x0, y0, x1, y1);
241 ButtonX = x;
242 ButtonY = y;
243 add_quats(q, CurQuat, CurQuat);
245 glutPostRedisplay();
250 static void
251 MouseButton(int button, int state, int x, int y)
253 if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
254 ButtonDown = GL_TRUE;
255 ButtonX = x;
256 ButtonY = y;
258 else if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
259 ButtonDown = GL_FALSE;
264 static void Init( int argc, char *argv[] )
266 GLboolean convolve = GL_FALSE;
267 GLboolean fullscreen = GL_FALSE;
268 int i;
270 for (i = 1; i < argc; i++) {
271 if (strcmp(argv[i], "-info")==0) {
272 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
273 printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
274 printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));
275 printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
277 else if (strcmp(argv[i], "-c")==0) {
278 convolve = GL_TRUE;
280 else if (strcmp(argv[i], "-f")==0) {
281 fullscreen = GL_TRUE;
285 if (convolve && !glutExtensionSupported("GL_ARB_imaging")) {
286 fprintf(stderr,
287 "GL_ARB_imaging is not supported, disabling convolution.\n");
288 exit(1);
292 if (fullscreen)
293 glutFullScreen();
295 /* Cylinder object */
297 static GLfloat height = 100.0;
298 static GLfloat radius = 40.0;
299 static GLint slices = 24; /* pie slices around Z axis */
300 static GLint stacks = 10; /* subdivisions along length of cylinder */
301 static GLint rings = 4; /* rings in the end disks */
302 GLUquadricObj *q = gluNewQuadric();
303 assert(q);
304 gluQuadricTexture(q, GL_TRUE);
306 CylinderObj = glGenLists(1);
307 glNewList(CylinderObj, GL_COMPILE);
309 glPushMatrix();
310 glTranslatef(0.0, 0.0, -0.5 * height);
312 glMatrixMode(GL_TEXTURE);
313 glLoadIdentity();
314 /*glScalef(8.0, 4.0, 2.0);*/
315 glMatrixMode(GL_MODELVIEW);
317 /* cylinder */
318 gluQuadricNormals(q, GL_SMOOTH);
319 gluQuadricTexture(q, GL_TRUE);
320 gluCylinder(q, radius, radius, height, slices, stacks);
322 /* end cap */
323 glMatrixMode(GL_TEXTURE);
324 glLoadIdentity();
325 glScalef(3.0, 3.0, 1.0);
326 glMatrixMode(GL_MODELVIEW);
328 glTranslatef(0.0, 0.0, height);
329 gluDisk(q, 0.0, radius, slices, rings);
331 /* other end cap */
332 glTranslatef(0.0, 0.0, -height);
333 gluQuadricOrientation(q, GLU_INSIDE);
334 gluDisk(q, 0.0, radius, slices, rings);
336 glPopMatrix();
338 glMatrixMode(GL_TEXTURE);
339 glLoadIdentity();
340 glMatrixMode(GL_MODELVIEW);
342 glEndList();
343 gluDeleteQuadric(q);
346 /* Teapot */
348 TeapotObj = glGenLists(1);
349 glNewList(TeapotObj, GL_COMPILE);
351 glFrontFace(GL_CW);
352 glutSolidTeapot(40.0);
353 glFrontFace(GL_CCW);
355 glEndList();
358 /* show cylinder by default */
359 Object = CylinderObj;
362 /* lighting */
363 glEnable(GL_LIGHTING);
365 GLfloat pos[4] = { 3, 3, 3, 1 };
366 glLightfv(GL_LIGHT0, GL_AMBIENT, Black);
367 glLightfv(GL_LIGHT0, GL_DIFFUSE, White);
368 glLightfv(GL_LIGHT0, GL_SPECULAR, White);
369 glLightfv(GL_LIGHT0, GL_POSITION, pos);
370 glEnable(GL_LIGHT0);
371 glMaterialfv(GL_FRONT, GL_AMBIENT, Black);
372 glMaterialf(GL_FRONT, GL_SHININESS, Shininess);
373 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
376 /* Base texture */
377 glGenTextures(1, &BaseTexture);
378 glBindTexture(GL_TEXTURE_2D, BaseTexture);
379 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
380 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
381 if (!LoadRGBMipmaps(BASE_TEXTURE_FILE, GL_RGB)) {
382 printf("Error: couldn't load texture image file %s\n", BASE_TEXTURE_FILE);
383 exit(1);
386 /* Specular texture */
387 glGenTextures(1, &SpecularTexture);
388 glBindTexture(GL_TEXTURE_2D, SpecularTexture);
389 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
390 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
391 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
392 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
393 if (convolve) {
394 /* use convolution to blur the texture to simulate a dull finish
395 * on the object.
397 GLubyte *img;
398 GLenum format;
399 GLint w, h;
400 GLfloat filter[FILTER_SIZE][FILTER_SIZE][4];
402 for (h = 0; h < FILTER_SIZE; h++) {
403 for (w = 0; w < FILTER_SIZE; w++) {
404 const GLfloat k = 1.0 / (FILTER_SIZE * FILTER_SIZE);
405 filter[h][w][0] = k;
406 filter[h][w][1] = k;
407 filter[h][w][2] = k;
408 filter[h][w][3] = k;
412 glEnable(GL_CONVOLUTION_2D);
413 glConvolutionParameteri(GL_CONVOLUTION_2D,
414 GL_CONVOLUTION_BORDER_MODE, GL_CONSTANT_BORDER);
415 glConvolutionFilter2D(GL_CONVOLUTION_2D, GL_RGBA,
416 FILTER_SIZE, FILTER_SIZE,
417 GL_RGBA, GL_FLOAT, filter);
419 img = LoadRGBImage(SPECULAR_TEXTURE_FILE, &w, &h, &format);
420 if (!img) {
421 printf("Error: couldn't load texture image file %s\n",
422 SPECULAR_TEXTURE_FILE);
423 exit(1);
426 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0,
427 format, GL_UNSIGNED_BYTE, img);
428 free(img);
430 else {
431 /* regular path */
432 if (!LoadRGBMipmaps(SPECULAR_TEXTURE_FILE, GL_RGB)) {
433 printf("Error: couldn't load texture image file %s\n",
434 SPECULAR_TEXTURE_FILE);
435 exit(1);
439 /* misc */
440 glEnable(GL_CULL_FACE);
441 glEnable(GL_TEXTURE_2D);
442 glEnable(GL_DEPTH_TEST);
443 glEnable(GL_NORMALIZE);
445 glPolygonOffset( -1, -1 );
449 int main( int argc, char *argv[] )
451 glutInitWindowSize(WinWidth, WinHeight);
452 glutInit( &argc, argv );
453 glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
454 Win = glutCreateWindow(argv[0] );
455 glewInit();
456 glutReshapeFunc( Reshape );
457 glutKeyboardFunc( Key );
458 glutDisplayFunc( Display );
459 glutMotionFunc(MouseMotion);
460 glutMouseFunc(MouseButton);
461 if (Animate)
462 glutIdleFunc( Idle );
464 glutCreateMenu(ModeMenu);
465 glutAddMenuEntry("Toggle Highlight", DO_SPEC_TEXTURE);
466 glutAddMenuEntry("Toggle Object", OBJECT);
467 glutAddMenuEntry("Toggle Animate", ANIMATE);
468 glutAddMenuEntry("Quit", QUIT);
469 glutAttachMenu(GLUT_RIGHT_BUTTON);
471 Init(argc, argv);
473 glutMainLoop();
474 return 0;