blob: 6713e042f604089c5ba3c7c5e36968536343a2bd [file] [log] [blame]
Brian Paulcefc42f2000-09-15 16:43:57 +00001/* $Id: reflect.c,v 1.4 2000/09/15 16:43:57 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 Paul7a6bb1b2000-04-12 01:08:30 +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;
56
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
150 glClearColor( 0.5, 0.5, 0.9, 1.0 );
151
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 }
jtgafb833d1999-08-19 00:55:39 +0000299
300 glutSwapBuffers();
Brian Paulcefc42f2000-09-15 16:43:57 +0000301
302 {
303 GLint t = glutGet(GLUT_ELAPSED_TIME);
304 Frames++;
305 if (t - T0 >= 5000) {
306 GLfloat seconds = (t - T0) / 1000.0;
307 GLfloat fps = Frames / seconds;
308 printf("%d frames in %g seconds = %g FPS\n", Frames, seconds, fps);
309 T0 = t;
310 Frames = 0;
311 }
312 }
jtgafb833d1999-08-19 00:55:39 +0000313}
jtgafb833d1999-08-19 00:55:39 +0000314
315
316static void Key( unsigned char key, int x, int y )
317{
318 (void) x;
319 (void) y;
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000320 if (key == 'd') {
321 ShowBuffer = GL_DEPTH;
322 }
323 else if (key == 's') {
324 ShowBuffer = GL_STENCIL;
325 }
326 else if (key==27) {
jtgafb833d1999-08-19 00:55:39 +0000327 exit(0);
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000328 }
329 else {
330 ShowBuffer = GL_NONE;
331 }
332 glutPostRedisplay();
jtgafb833d1999-08-19 00:55:39 +0000333}
334
335
336static void SpecialKey( int key, int x, int y )
337{
338 (void) x;
339 (void) y;
340 switch (key) {
341 case GLUT_KEY_UP:
342 xrot += 3.0;
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000343 if ( xrot > 85 )
344 xrot = 85;
jtgafb833d1999-08-19 00:55:39 +0000345 break;
346 case GLUT_KEY_DOWN:
347 xrot -= 3.0;
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000348 if ( xrot < 5 )
349 xrot = 5;
jtgafb833d1999-08-19 00:55:39 +0000350 break;
351 case GLUT_KEY_LEFT:
352 yrot += 3.0;
353 break;
354 case GLUT_KEY_RIGHT:
355 yrot -= 3.0;
356 break;
357 }
358 glutPostRedisplay();
359}
360
361
362
363static void idle( void )
364{
365 spin += 2.0;
366 yrot += 3.0;
367 glutPostRedisplay();
368}
369
370
371
372int main( int argc, char *argv[] )
373{
Brian Paul479fab62000-06-15 14:25:48 +0000374 glutInit(&argc, argv);
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000375 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH | GLUT_STENCIL);
jtgafb833d1999-08-19 00:55:39 +0000376 glutInitWindowPosition( 0, 0 );
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000377 glutInitWindowSize( Width, Height );
jtgafb833d1999-08-19 00:55:39 +0000378 glutCreateWindow(argv[0]);
379 glutReshapeFunc(reshape);
380 glutDisplayFunc(draw_scene);
381 glutKeyboardFunc(Key);
382 glutSpecialFunc(SpecialKey);
383 glutIdleFunc(idle);
jtgafb833d1999-08-19 00:55:39 +0000384 init();
jtgafb833d1999-08-19 00:55:39 +0000385 glutMainLoop();
386 return 0;
387}