blob: d259d7b718871cac9bf6860aed184a4d9ff023f7 [file] [log] [blame]
jtgafb833d1999-08-19 00:55:39 +00001
2/*
3 * Demo of a reflective, texture-mapped surface with OpenGL.
4 * Brian Paul August 14, 1995 This file is in the public domain.
5 *
6 * Hardware texture mapping is highly recommended!
7 *
8 * The basic steps are:
9 * 1. Render the reflective object (a polygon) from the normal viewpoint,
10 * setting the stencil planes = 1.
11 * 2. Render the scene from a special viewpoint: the viewpoint which
12 * is on the opposite side of the reflective plane. Only draw where
13 * stencil = 1. This draws the objects in the reflective surface.
14 * 3. Render the scene from the original viewpoint. This draws the
15 * objects in the normal fashion. Use blending when drawing
16 * the reflective, textured surface.
17 *
18 * This is a very crude demo. It could be much better.
19 */
20
21/*
Brian Paul7a6bb1b2000-04-12 01:08:30 +000022 * Authors:
23 * Brian Paul
24 * Dirk Reiners (reiners@igd.fhg.de) made some modifications to this code.
25 * Mark Kilgard (April 1997)
26 * Brian Paul (April 2000 - added keyboard d/s options)
jtgafb833d1999-08-19 00:55:39 +000027 */
28
jtgafb833d1999-08-19 00:55:39 +000029
30#include <math.h>
31#include <stdio.h>
32#include <stdlib.h>
33#include "GL/glut.h"
Brian Paul92eddb02005-01-09 17:37:50 +000034#include "showbuffer.h"
35#include "readtex.h"
jtgafb833d1999-08-19 00:55:39 +000036
37
38#define DEG2RAD (3.14159/180.0)
39
jtgafb833d1999-08-19 00:55:39 +000040#define TABLE_TEXTURE "../images/tile.rgb"
41
Brian Paul7a6bb1b2000-04-12 01:08:30 +000042static GLint ImgWidth, ImgHeight;
jtgafb833d1999-08-19 00:55:39 +000043static GLenum ImgFormat;
44static GLubyte *Image = NULL;
45
46#define MAX_OBJECTS 2
jtgafb833d1999-08-19 00:55:39 +000047static GLint table_list;
48static GLint objects_list[MAX_OBJECTS];
49
jtgafb833d1999-08-19 00:55:39 +000050static GLfloat xrot, yrot;
51static GLfloat spin;
52
Brian Paul7a6bb1b2000-04-12 01:08:30 +000053static GLint Width = 400, Height = 300;
54static GLenum ShowBuffer = GL_NONE;
Brian Paul2b2e6212001-01-23 23:43:53 +000055static GLboolean Anim = GL_TRUE;
Brian Paul7a6bb1b2000-04-12 01:08:30 +000056
Brian Paulcefc42f2000-09-15 16:43:57 +000057/* performance info */
58static GLint T0 = 0;
59static GLint Frames = 0;
jtgafb833d1999-08-19 00:55:39 +000060
61
62static void make_table( void )
63{
64 static GLfloat table_mat[] = { 1.0, 1.0, 1.0, 0.6 };
65 static GLfloat gray[] = { 0.4, 0.4, 0.4, 1.0 };
66
67 table_list = glGenLists(1);
68 glNewList( table_list, GL_COMPILE );
69
70 /* load table's texture */
71 glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, table_mat );
72/* glMaterialfv( GL_FRONT, GL_EMISSION, gray );*/
73 glMaterialfv( GL_FRONT, GL_DIFFUSE, table_mat );
74 glMaterialfv( GL_FRONT, GL_AMBIENT, gray );
75
76 /* draw textured square for the table */
77 glPushMatrix();
78 glScalef( 4.0, 4.0, 4.0 );
79 glBegin( GL_POLYGON );
80 glNormal3f( 0.0, 1.0, 0.0 );
81 glTexCoord2f( 0.0, 0.0 ); glVertex3f( -1.0, 0.0, 1.0 );
82 glTexCoord2f( 1.0, 0.0 ); glVertex3f( 1.0, 0.0, 1.0 );
83 glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 0.0, -1.0 );
84 glTexCoord2f( 0.0, 1.0 ); glVertex3f( -1.0, 0.0, -1.0 );
85 glEnd();
86 glPopMatrix();
87
88 glDisable( GL_TEXTURE_2D );
89
90 glEndList();
91}
92
93
94static void make_objects( void )
95{
96 GLUquadricObj *q;
97
98 static GLfloat cyan[] = { 0.0, 1.0, 1.0, 1.0 };
99 static GLfloat green[] = { 0.2, 1.0, 0.2, 1.0 };
100 static GLfloat black[] = { 0.0, 0.0, 0.0, 0.0 };
101
102 q = gluNewQuadric();
103 gluQuadricDrawStyle( q, GLU_FILL );
104 gluQuadricNormals( q, GLU_SMOOTH );
105
106 objects_list[0] = glGenLists(1);
107 glNewList( objects_list[0], GL_COMPILE );
108 glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, cyan );
109 glMaterialfv( GL_FRONT, GL_EMISSION, black );
110 gluCylinder( q, 0.5, 0.5, 1.0, 15, 1 );
111 glEndList();
112
113 objects_list[1] = glGenLists(1);
114 glNewList( objects_list[1], GL_COMPILE );
115 glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green );
116 glMaterialfv( GL_FRONT, GL_EMISSION, black );
117 gluCylinder( q, 1.5, 0.0, 2.5, 15, 1 );
118 glEndList();
119}
120
121
jtgafb833d1999-08-19 00:55:39 +0000122static void init( void )
123{
124 make_table();
125 make_objects();
126
jtgafb833d1999-08-19 00:55:39 +0000127 Image = LoadRGBImage( TABLE_TEXTURE, &ImgWidth, &ImgHeight, &ImgFormat );
128 if (!Image) {
129 printf("Couldn't read %s\n", TABLE_TEXTURE);
130 exit(0);
131 }
132
133 gluBuild2DMipmaps(GL_TEXTURE_2D, 3, ImgWidth, ImgHeight,
134 ImgFormat, GL_UNSIGNED_BYTE, Image);
135
136 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
137 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
138 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
139 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
jtgafb833d1999-08-19 00:55:39 +0000140
141 xrot = 30.0;
142 yrot = 50.0;
143 spin = 0.0;
144
jtgafb833d1999-08-19 00:55:39 +0000145 glShadeModel( GL_FLAT );
146
147 glEnable( GL_LIGHT0 );
148 glEnable( GL_LIGHTING );
149
Brian Paul73ccfa02001-04-25 15:51:32 +0000150 glClearColor( 0.5, 0.5, 0.9, 0.0 );
jtgafb833d1999-08-19 00:55:39 +0000151
152 glEnable( GL_NORMALIZE );
153}
154
155
156
157static void reshape(int w, int h)
158{
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000159 GLfloat yAspect = 2.5;
160 GLfloat xAspect = yAspect * (float) w / (float) h;
161 Width = w;
162 Height = h;
jtgafb833d1999-08-19 00:55:39 +0000163 glViewport(0, 0, w, h);
164 glMatrixMode(GL_PROJECTION);
165 glLoadIdentity();
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000166 glFrustum( -xAspect, xAspect, -yAspect, yAspect, 10.0, 30.0 );
jtgafb833d1999-08-19 00:55:39 +0000167 glMatrixMode(GL_MODELVIEW);
168 glLoadIdentity();
169}
170
171
172
173static void draw_objects( GLfloat eyex, GLfloat eyey, GLfloat eyez )
174{
175 (void) eyex;
176 (void) eyey;
177 (void) eyez;
178#ifndef USE_ZBUFFER
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000179 if (eyex<0.5) {
jtgafb833d1999-08-19 00:55:39 +0000180#endif
181 glPushMatrix();
182 glTranslatef( 1.0, 1.5, 0.0 );
183 glRotatef( spin, 1.0, 0.5, 0.0 );
184 glRotatef( 0.5*spin, 0.0, 0.5, 1.0 );
185 glCallList( objects_list[0] );
186 glPopMatrix();
187
188 glPushMatrix();
189 glTranslatef( -1.0, 0.85+3.0*fabs( cos(0.01*spin) ), 0.0 );
190 glRotatef( 0.5*spin, 0.0, 0.5, 1.0 );
191 glRotatef( spin, 1.0, 0.5, 0.0 );
192 glScalef( 0.5, 0.5, 0.5 );
193 glCallList( objects_list[1] );
194 glPopMatrix();
195#ifndef USE_ZBUFFER
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000196 }
197 else {
jtgafb833d1999-08-19 00:55:39 +0000198 glPushMatrix();
199 glTranslatef( -1.0, 0.85+3.0*fabs( cos(0.01*spin) ), 0.0 );
200 glRotatef( 0.5*spin, 0.0, 0.5, 1.0 );
201 glRotatef( spin, 1.0, 0.5, 0.0 );
202 glScalef( 0.5, 0.5, 0.5 );
203 glCallList( objects_list[1] );
204 glPopMatrix();
205
206 glPushMatrix();
207 glTranslatef( 1.0, 1.5, 0.0 );
208 glRotatef( spin, 1.0, 0.5, 0.0 );
209 glRotatef( 0.5*spin, 0.0, 0.5, 1.0 );
210 glCallList( objects_list[0] );
211 glPopMatrix();
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000212 }
jtgafb833d1999-08-19 00:55:39 +0000213#endif
214}
215
216
217
218static void draw_table( void )
219{
220 glCallList( table_list );
221}
222
223
224
225static void draw_scene( void )
226{
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000227 static GLfloat light_pos[] = { 0.0, 20.0, 0.0, 1.0 };
jtgafb833d1999-08-19 00:55:39 +0000228 GLfloat dist = 20.0;
229 GLfloat eyex, eyey, eyez;
230
231 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
232
233
234 eyex = dist * cos(yrot*DEG2RAD) * cos(xrot*DEG2RAD);
235 eyez = dist * sin(yrot*DEG2RAD) * cos(xrot*DEG2RAD);
236 eyey = dist * sin(xrot*DEG2RAD);
237
238 /* view from top */
239 glPushMatrix();
240 gluLookAt( eyex, eyey, eyez, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 );
241
242 glLightfv( GL_LIGHT0, GL_POSITION, light_pos );
243
244 /* draw table into stencil planes */
jtgafb833d1999-08-19 00:55:39 +0000245 glDisable( GL_DEPTH_TEST );
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000246 glEnable( GL_STENCIL_TEST );
jtgafb833d1999-08-19 00:55:39 +0000247 glStencilFunc( GL_ALWAYS, 1, 0xffffffff );
248 glStencilOp( GL_REPLACE, GL_REPLACE, GL_REPLACE );
249 glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
250 draw_table();
251 glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
252
jtgafb833d1999-08-19 00:55:39 +0000253 glEnable( GL_DEPTH_TEST );
jtgafb833d1999-08-19 00:55:39 +0000254
255 /* render view from below (reflected viewport) */
256 /* only draw where stencil==1 */
257 if (eyey>0.0) {
258 glPushMatrix();
259
260 glStencilFunc( GL_EQUAL, 1, 0xffffffff ); /* draw if ==1 */
261 glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
262 glScalef( 1.0, -1.0, 1.0 );
263
264 /* Reposition light in reflected space. */
265 glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
266
267 draw_objects(eyex, eyey, eyez);
268 glPopMatrix();
269
270 /* Restore light's original unreflected position. */
271 glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
272 }
273
274 glDisable( GL_STENCIL_TEST );
275
276 glEnable( GL_BLEND );
277 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
278
jtgafb833d1999-08-19 00:55:39 +0000279 glEnable( GL_TEXTURE_2D );
jtgafb833d1999-08-19 00:55:39 +0000280 draw_table();
281 glDisable( GL_TEXTURE_2D );
282 glDisable( GL_BLEND );
283
284 /* view from top */
285 glPushMatrix();
286
287 draw_objects(eyex, eyey, eyez);
288
289 glPopMatrix();
290
291 glPopMatrix();
292
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000293 if (ShowBuffer == GL_DEPTH) {
294 ShowDepthBuffer(Width, Height, 1.0, 0.0);
295 }
296 else if (ShowBuffer == GL_STENCIL) {
297 ShowStencilBuffer(Width, Height, 255.0, 0.0);
298 }
Brian Paul73ccfa02001-04-25 15:51:32 +0000299 else if (ShowBuffer == GL_ALPHA) {
300 ShowAlphaBuffer(Width, Height);
301 }
jtgafb833d1999-08-19 00:55:39 +0000302
303 glutSwapBuffers();
Brian Paulcefc42f2000-09-15 16:43:57 +0000304
305 {
306 GLint t = glutGet(GLUT_ELAPSED_TIME);
307 Frames++;
308 if (t - T0 >= 5000) {
309 GLfloat seconds = (t - T0) / 1000.0;
310 GLfloat fps = Frames / seconds;
311 printf("%d frames in %g seconds = %g FPS\n", Frames, seconds, fps);
312 T0 = t;
313 Frames = 0;
314 }
315 }
jtgafb833d1999-08-19 00:55:39 +0000316}
jtgafb833d1999-08-19 00:55:39 +0000317
318
Brian Paul2b2e6212001-01-23 23:43:53 +0000319static void idle( void )
320{
Brian Paul92eddb02005-01-09 17:37:50 +0000321 static double t0 = -1.;
322 double dt, t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
323 if (t0 < 0.0)
324 t0 = t;
325 dt = t - t0;
326 t0 = t;
327 spin += 60.0 * dt;
328 yrot += 90.0 * dt;
Brian Paul2b2e6212001-01-23 23:43:53 +0000329 glutPostRedisplay();
330}
331
332
jtgafb833d1999-08-19 00:55:39 +0000333static void Key( unsigned char key, int x, int y )
334{
335 (void) x;
336 (void) y;
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000337 if (key == 'd') {
338 ShowBuffer = GL_DEPTH;
339 }
340 else if (key == 's') {
341 ShowBuffer = GL_STENCIL;
342 }
Brian Paul73ccfa02001-04-25 15:51:32 +0000343 else if (key == 'a') {
344 ShowBuffer = GL_ALPHA;
345 }
Brian Paul2b2e6212001-01-23 23:43:53 +0000346 else if (key == ' ') {
347 Anim = !Anim;
348 if (Anim)
349 glutIdleFunc(idle);
350 else
351 glutIdleFunc(NULL);
352 }
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000353 else if (key==27) {
jtgafb833d1999-08-19 00:55:39 +0000354 exit(0);
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000355 }
356 else {
357 ShowBuffer = GL_NONE;
358 }
359 glutPostRedisplay();
jtgafb833d1999-08-19 00:55:39 +0000360}
361
362
363static void SpecialKey( int key, int x, int y )
364{
365 (void) x;
366 (void) y;
367 switch (key) {
368 case GLUT_KEY_UP:
369 xrot += 3.0;
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000370 if ( xrot > 85 )
371 xrot = 85;
jtgafb833d1999-08-19 00:55:39 +0000372 break;
373 case GLUT_KEY_DOWN:
374 xrot -= 3.0;
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000375 if ( xrot < 5 )
376 xrot = 5;
jtgafb833d1999-08-19 00:55:39 +0000377 break;
378 case GLUT_KEY_LEFT:
379 yrot += 3.0;
380 break;
381 case GLUT_KEY_RIGHT:
382 yrot -= 3.0;
383 break;
384 }
385 glutPostRedisplay();
386}
387
388
jtgafb833d1999-08-19 00:55:39 +0000389int main( int argc, char *argv[] )
390{
Brian Paul479fab62000-06-15 14:25:48 +0000391 glutInit(&argc, argv);
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000392 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH | GLUT_STENCIL);
jtgafb833d1999-08-19 00:55:39 +0000393 glutInitWindowPosition( 0, 0 );
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000394 glutInitWindowSize( Width, Height );
jtgafb833d1999-08-19 00:55:39 +0000395 glutCreateWindow(argv[0]);
396 glutReshapeFunc(reshape);
397 glutDisplayFunc(draw_scene);
398 glutKeyboardFunc(Key);
399 glutSpecialFunc(SpecialKey);
400 glutIdleFunc(idle);
jtgafb833d1999-08-19 00:55:39 +0000401 init();
jtgafb833d1999-08-19 00:55:39 +0000402 glutMainLoop();
403 return 0;
404}