blob: 0c734a030cbf31f7913a09172c19a84325e4b06b [file] [log] [blame]
Brian Paul73ccfa02001-04-25 15:51:32 +00001/* $Id: reflect.c,v 1.7 2001/04/25 15:51:32 brianp Exp $ */
jtgafb833d1999-08-19 00:55:39 +00002
3/*
4 * Demo of a reflective, texture-mapped surface with OpenGL.
5 * Brian Paul August 14, 1995 This file is in the public domain.
6 *
7 * Hardware texture mapping is highly recommended!
8 *
9 * The basic steps are:
10 * 1. Render the reflective object (a polygon) from the normal viewpoint,
11 * setting the stencil planes = 1.
12 * 2. Render the scene from a special viewpoint: the viewpoint which
13 * is on the opposite side of the reflective plane. Only draw where
14 * stencil = 1. This draws the objects in the reflective surface.
15 * 3. Render the scene from the original viewpoint. This draws the
16 * objects in the normal fashion. Use blending when drawing
17 * the reflective, textured surface.
18 *
19 * This is a very crude demo. It could be much better.
20 */
21
22/*
Brian Paul7a6bb1b2000-04-12 01:08:30 +000023 * Authors:
24 * Brian Paul
25 * Dirk Reiners (reiners@igd.fhg.de) made some modifications to this code.
26 * Mark Kilgard (April 1997)
27 * Brian Paul (April 2000 - added keyboard d/s options)
jtgafb833d1999-08-19 00:55:39 +000028 */
29
jtgafb833d1999-08-19 00:55:39 +000030
31#include <math.h>
32#include <stdio.h>
33#include <stdlib.h>
34#include "GL/glut.h"
Brian Paul2b2e6212001-01-23 23:43:53 +000035#include "../util/showbuffer.c"
36#include "../util/readtex.c"
jtgafb833d1999-08-19 00:55:39 +000037
38
39#define DEG2RAD (3.14159/180.0)
40
jtgafb833d1999-08-19 00:55:39 +000041#define TABLE_TEXTURE "../images/tile.rgb"
42
Brian Paul7a6bb1b2000-04-12 01:08:30 +000043static GLint ImgWidth, ImgHeight;
jtgafb833d1999-08-19 00:55:39 +000044static GLenum ImgFormat;
45static GLubyte *Image = NULL;
46
47#define MAX_OBJECTS 2
jtgafb833d1999-08-19 00:55:39 +000048static GLint table_list;
49static GLint objects_list[MAX_OBJECTS];
50
jtgafb833d1999-08-19 00:55:39 +000051static GLfloat xrot, yrot;
52static GLfloat spin;
53
Brian Paul7a6bb1b2000-04-12 01:08:30 +000054static GLint Width = 400, Height = 300;
55static GLenum ShowBuffer = GL_NONE;
Brian Paul2b2e6212001-01-23 23:43:53 +000056static GLboolean Anim = GL_TRUE;
Brian Paul7a6bb1b2000-04-12 01:08:30 +000057
Brian Paulcefc42f2000-09-15 16:43:57 +000058/* performance info */
59static GLint T0 = 0;
60static GLint Frames = 0;
jtgafb833d1999-08-19 00:55:39 +000061
62
63static void make_table( void )
64{
65 static GLfloat table_mat[] = { 1.0, 1.0, 1.0, 0.6 };
66 static GLfloat gray[] = { 0.4, 0.4, 0.4, 1.0 };
67
68 table_list = glGenLists(1);
69 glNewList( table_list, GL_COMPILE );
70
71 /* load table's texture */
72 glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, table_mat );
73/* glMaterialfv( GL_FRONT, GL_EMISSION, gray );*/
74 glMaterialfv( GL_FRONT, GL_DIFFUSE, table_mat );
75 glMaterialfv( GL_FRONT, GL_AMBIENT, gray );
76
77 /* draw textured square for the table */
78 glPushMatrix();
79 glScalef( 4.0, 4.0, 4.0 );
80 glBegin( GL_POLYGON );
81 glNormal3f( 0.0, 1.0, 0.0 );
82 glTexCoord2f( 0.0, 0.0 ); glVertex3f( -1.0, 0.0, 1.0 );
83 glTexCoord2f( 1.0, 0.0 ); glVertex3f( 1.0, 0.0, 1.0 );
84 glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 0.0, -1.0 );
85 glTexCoord2f( 0.0, 1.0 ); glVertex3f( -1.0, 0.0, -1.0 );
86 glEnd();
87 glPopMatrix();
88
89 glDisable( GL_TEXTURE_2D );
90
91 glEndList();
92}
93
94
95static void make_objects( void )
96{
97 GLUquadricObj *q;
98
99 static GLfloat cyan[] = { 0.0, 1.0, 1.0, 1.0 };
100 static GLfloat green[] = { 0.2, 1.0, 0.2, 1.0 };
101 static GLfloat black[] = { 0.0, 0.0, 0.0, 0.0 };
102
103 q = gluNewQuadric();
104 gluQuadricDrawStyle( q, GLU_FILL );
105 gluQuadricNormals( q, GLU_SMOOTH );
106
107 objects_list[0] = glGenLists(1);
108 glNewList( objects_list[0], GL_COMPILE );
109 glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, cyan );
110 glMaterialfv( GL_FRONT, GL_EMISSION, black );
111 gluCylinder( q, 0.5, 0.5, 1.0, 15, 1 );
112 glEndList();
113
114 objects_list[1] = glGenLists(1);
115 glNewList( objects_list[1], GL_COMPILE );
116 glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green );
117 glMaterialfv( GL_FRONT, GL_EMISSION, black );
118 gluCylinder( q, 1.5, 0.0, 2.5, 15, 1 );
119 glEndList();
120}
121
122
jtgafb833d1999-08-19 00:55:39 +0000123static void init( void )
124{
125 make_table();
126 make_objects();
127
jtgafb833d1999-08-19 00:55:39 +0000128 Image = LoadRGBImage( TABLE_TEXTURE, &ImgWidth, &ImgHeight, &ImgFormat );
129 if (!Image) {
130 printf("Couldn't read %s\n", TABLE_TEXTURE);
131 exit(0);
132 }
133
134 gluBuild2DMipmaps(GL_TEXTURE_2D, 3, ImgWidth, ImgHeight,
135 ImgFormat, GL_UNSIGNED_BYTE, Image);
136
137 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
138 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
139 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
140 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
jtgafb833d1999-08-19 00:55:39 +0000141
142 xrot = 30.0;
143 yrot = 50.0;
144 spin = 0.0;
145
jtgafb833d1999-08-19 00:55:39 +0000146 glShadeModel( GL_FLAT );
147
148 glEnable( GL_LIGHT0 );
149 glEnable( GL_LIGHTING );
150
Brian Paul73ccfa02001-04-25 15:51:32 +0000151 glClearColor( 0.5, 0.5, 0.9, 0.0 );
jtgafb833d1999-08-19 00:55:39 +0000152
153 glEnable( GL_NORMALIZE );
154}
155
156
157
158static void reshape(int w, int h)
159{
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000160 GLfloat yAspect = 2.5;
161 GLfloat xAspect = yAspect * (float) w / (float) h;
162 Width = w;
163 Height = h;
jtgafb833d1999-08-19 00:55:39 +0000164 glViewport(0, 0, w, h);
165 glMatrixMode(GL_PROJECTION);
166 glLoadIdentity();
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000167 glFrustum( -xAspect, xAspect, -yAspect, yAspect, 10.0, 30.0 );
jtgafb833d1999-08-19 00:55:39 +0000168 glMatrixMode(GL_MODELVIEW);
169 glLoadIdentity();
170}
171
172
173
174static void draw_objects( GLfloat eyex, GLfloat eyey, GLfloat eyez )
175{
176 (void) eyex;
177 (void) eyey;
178 (void) eyez;
179#ifndef USE_ZBUFFER
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000180 if (eyex<0.5) {
jtgafb833d1999-08-19 00:55:39 +0000181#endif
182 glPushMatrix();
183 glTranslatef( 1.0, 1.5, 0.0 );
184 glRotatef( spin, 1.0, 0.5, 0.0 );
185 glRotatef( 0.5*spin, 0.0, 0.5, 1.0 );
186 glCallList( objects_list[0] );
187 glPopMatrix();
188
189 glPushMatrix();
190 glTranslatef( -1.0, 0.85+3.0*fabs( cos(0.01*spin) ), 0.0 );
191 glRotatef( 0.5*spin, 0.0, 0.5, 1.0 );
192 glRotatef( spin, 1.0, 0.5, 0.0 );
193 glScalef( 0.5, 0.5, 0.5 );
194 glCallList( objects_list[1] );
195 glPopMatrix();
196#ifndef USE_ZBUFFER
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000197 }
198 else {
jtgafb833d1999-08-19 00:55:39 +0000199 glPushMatrix();
200 glTranslatef( -1.0, 0.85+3.0*fabs( cos(0.01*spin) ), 0.0 );
201 glRotatef( 0.5*spin, 0.0, 0.5, 1.0 );
202 glRotatef( spin, 1.0, 0.5, 0.0 );
203 glScalef( 0.5, 0.5, 0.5 );
204 glCallList( objects_list[1] );
205 glPopMatrix();
206
207 glPushMatrix();
208 glTranslatef( 1.0, 1.5, 0.0 );
209 glRotatef( spin, 1.0, 0.5, 0.0 );
210 glRotatef( 0.5*spin, 0.0, 0.5, 1.0 );
211 glCallList( objects_list[0] );
212 glPopMatrix();
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000213 }
jtgafb833d1999-08-19 00:55:39 +0000214#endif
215}
216
217
218
219static void draw_table( void )
220{
221 glCallList( table_list );
222}
223
224
225
226static void draw_scene( void )
227{
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000228 static GLfloat light_pos[] = { 0.0, 20.0, 0.0, 1.0 };
jtgafb833d1999-08-19 00:55:39 +0000229 GLfloat dist = 20.0;
230 GLfloat eyex, eyey, eyez;
231
232 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
233
234
235 eyex = dist * cos(yrot*DEG2RAD) * cos(xrot*DEG2RAD);
236 eyez = dist * sin(yrot*DEG2RAD) * cos(xrot*DEG2RAD);
237 eyey = dist * sin(xrot*DEG2RAD);
238
239 /* view from top */
240 glPushMatrix();
241 gluLookAt( eyex, eyey, eyez, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 );
242
243 glLightfv( GL_LIGHT0, GL_POSITION, light_pos );
244
245 /* draw table into stencil planes */
jtgafb833d1999-08-19 00:55:39 +0000246 glDisable( GL_DEPTH_TEST );
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000247 glEnable( GL_STENCIL_TEST );
jtgafb833d1999-08-19 00:55:39 +0000248 glStencilFunc( GL_ALWAYS, 1, 0xffffffff );
249 glStencilOp( GL_REPLACE, GL_REPLACE, GL_REPLACE );
250 glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
251 draw_table();
252 glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
253
jtgafb833d1999-08-19 00:55:39 +0000254 glEnable( GL_DEPTH_TEST );
jtgafb833d1999-08-19 00:55:39 +0000255
256 /* render view from below (reflected viewport) */
257 /* only draw where stencil==1 */
258 if (eyey>0.0) {
259 glPushMatrix();
260
261 glStencilFunc( GL_EQUAL, 1, 0xffffffff ); /* draw if ==1 */
262 glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
263 glScalef( 1.0, -1.0, 1.0 );
264
265 /* Reposition light in reflected space. */
266 glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
267
268 draw_objects(eyex, eyey, eyez);
269 glPopMatrix();
270
271 /* Restore light's original unreflected position. */
272 glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
273 }
274
275 glDisable( GL_STENCIL_TEST );
276
277 glEnable( GL_BLEND );
278 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
279
jtgafb833d1999-08-19 00:55:39 +0000280 glEnable( GL_TEXTURE_2D );
jtgafb833d1999-08-19 00:55:39 +0000281 draw_table();
282 glDisable( GL_TEXTURE_2D );
283 glDisable( GL_BLEND );
284
285 /* view from top */
286 glPushMatrix();
287
288 draw_objects(eyex, eyey, eyez);
289
290 glPopMatrix();
291
292 glPopMatrix();
293
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000294 if (ShowBuffer == GL_DEPTH) {
295 ShowDepthBuffer(Width, Height, 1.0, 0.0);
296 }
297 else if (ShowBuffer == GL_STENCIL) {
298 ShowStencilBuffer(Width, Height, 255.0, 0.0);
299 }
Brian Paul73ccfa02001-04-25 15:51:32 +0000300 else if (ShowBuffer == GL_ALPHA) {
301 ShowAlphaBuffer(Width, Height);
302 }
jtgafb833d1999-08-19 00:55:39 +0000303
304 glutSwapBuffers();
Brian Paulcefc42f2000-09-15 16:43:57 +0000305
306 {
307 GLint t = glutGet(GLUT_ELAPSED_TIME);
308 Frames++;
309 if (t - T0 >= 5000) {
310 GLfloat seconds = (t - T0) / 1000.0;
311 GLfloat fps = Frames / seconds;
312 printf("%d frames in %g seconds = %g FPS\n", Frames, seconds, fps);
313 T0 = t;
314 Frames = 0;
315 }
316 }
jtgafb833d1999-08-19 00:55:39 +0000317}
jtgafb833d1999-08-19 00:55:39 +0000318
319
Brian Paul2b2e6212001-01-23 23:43:53 +0000320static void idle( void )
321{
322 spin += 2.0;
323 yrot += 3.0;
324 glutPostRedisplay();
325}
326
327
jtgafb833d1999-08-19 00:55:39 +0000328static void Key( unsigned char key, int x, int y )
329{
330 (void) x;
331 (void) y;
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000332 if (key == 'd') {
333 ShowBuffer = GL_DEPTH;
334 }
335 else if (key == 's') {
336 ShowBuffer = GL_STENCIL;
337 }
Brian Paul73ccfa02001-04-25 15:51:32 +0000338 else if (key == 'a') {
339 ShowBuffer = GL_ALPHA;
340 }
Brian Paul2b2e6212001-01-23 23:43:53 +0000341 else if (key == ' ') {
342 Anim = !Anim;
343 if (Anim)
344 glutIdleFunc(idle);
345 else
346 glutIdleFunc(NULL);
347 }
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000348 else if (key==27) {
jtgafb833d1999-08-19 00:55:39 +0000349 exit(0);
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000350 }
351 else {
352 ShowBuffer = GL_NONE;
353 }
354 glutPostRedisplay();
jtgafb833d1999-08-19 00:55:39 +0000355}
356
357
358static void SpecialKey( int key, int x, int y )
359{
360 (void) x;
361 (void) y;
362 switch (key) {
363 case GLUT_KEY_UP:
364 xrot += 3.0;
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000365 if ( xrot > 85 )
366 xrot = 85;
jtgafb833d1999-08-19 00:55:39 +0000367 break;
368 case GLUT_KEY_DOWN:
369 xrot -= 3.0;
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000370 if ( xrot < 5 )
371 xrot = 5;
jtgafb833d1999-08-19 00:55:39 +0000372 break;
373 case GLUT_KEY_LEFT:
374 yrot += 3.0;
375 break;
376 case GLUT_KEY_RIGHT:
377 yrot -= 3.0;
378 break;
379 }
380 glutPostRedisplay();
381}
382
383
jtgafb833d1999-08-19 00:55:39 +0000384int main( int argc, char *argv[] )
385{
Brian Paul479fab62000-06-15 14:25:48 +0000386 glutInit(&argc, argv);
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000387 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH | GLUT_STENCIL);
jtgafb833d1999-08-19 00:55:39 +0000388 glutInitWindowPosition( 0, 0 );
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000389 glutInitWindowSize( Width, Height );
jtgafb833d1999-08-19 00:55:39 +0000390 glutCreateWindow(argv[0]);
391 glutReshapeFunc(reshape);
392 glutDisplayFunc(draw_scene);
393 glutKeyboardFunc(Key);
394 glutSpecialFunc(SpecialKey);
395 glutIdleFunc(idle);
jtgafb833d1999-08-19 00:55:39 +0000396 init();
jtgafb833d1999-08-19 00:55:39 +0000397 glutMainLoop();
398 return 0;
399}