blob: 8ddb9726b159386d3446872c16c0b12b1a18819f [file] [log] [blame]
Brian Paul7a6bb1b2000-04-12 01:08:30 +00001/* $Id: reflect.c,v 1.2 2000/04/12 01:08:30 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
jtgafb833d1999-08-19 00:55:39 +000057
58
59static void make_table( void )
60{
61 static GLfloat table_mat[] = { 1.0, 1.0, 1.0, 0.6 };
62 static GLfloat gray[] = { 0.4, 0.4, 0.4, 1.0 };
63
64 table_list = glGenLists(1);
65 glNewList( table_list, GL_COMPILE );
66
67 /* load table's texture */
68 glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, table_mat );
69/* glMaterialfv( GL_FRONT, GL_EMISSION, gray );*/
70 glMaterialfv( GL_FRONT, GL_DIFFUSE, table_mat );
71 glMaterialfv( GL_FRONT, GL_AMBIENT, gray );
72
73 /* draw textured square for the table */
74 glPushMatrix();
75 glScalef( 4.0, 4.0, 4.0 );
76 glBegin( GL_POLYGON );
77 glNormal3f( 0.0, 1.0, 0.0 );
78 glTexCoord2f( 0.0, 0.0 ); glVertex3f( -1.0, 0.0, 1.0 );
79 glTexCoord2f( 1.0, 0.0 ); glVertex3f( 1.0, 0.0, 1.0 );
80 glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 0.0, -1.0 );
81 glTexCoord2f( 0.0, 1.0 ); glVertex3f( -1.0, 0.0, -1.0 );
82 glEnd();
83 glPopMatrix();
84
85 glDisable( GL_TEXTURE_2D );
86
87 glEndList();
88}
89
90
91static void make_objects( void )
92{
93 GLUquadricObj *q;
94
95 static GLfloat cyan[] = { 0.0, 1.0, 1.0, 1.0 };
96 static GLfloat green[] = { 0.2, 1.0, 0.2, 1.0 };
97 static GLfloat black[] = { 0.0, 0.0, 0.0, 0.0 };
98
99 q = gluNewQuadric();
100 gluQuadricDrawStyle( q, GLU_FILL );
101 gluQuadricNormals( q, GLU_SMOOTH );
102
103 objects_list[0] = glGenLists(1);
104 glNewList( objects_list[0], GL_COMPILE );
105 glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, cyan );
106 glMaterialfv( GL_FRONT, GL_EMISSION, black );
107 gluCylinder( q, 0.5, 0.5, 1.0, 15, 1 );
108 glEndList();
109
110 objects_list[1] = glGenLists(1);
111 glNewList( objects_list[1], GL_COMPILE );
112 glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green );
113 glMaterialfv( GL_FRONT, GL_EMISSION, black );
114 gluCylinder( q, 1.5, 0.0, 2.5, 15, 1 );
115 glEndList();
116}
117
118
jtgafb833d1999-08-19 00:55:39 +0000119static void init( void )
120{
121 make_table();
122 make_objects();
123
jtgafb833d1999-08-19 00:55:39 +0000124 Image = LoadRGBImage( TABLE_TEXTURE, &ImgWidth, &ImgHeight, &ImgFormat );
125 if (!Image) {
126 printf("Couldn't read %s\n", TABLE_TEXTURE);
127 exit(0);
128 }
129
130 gluBuild2DMipmaps(GL_TEXTURE_2D, 3, ImgWidth, ImgHeight,
131 ImgFormat, GL_UNSIGNED_BYTE, Image);
132
133 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
134 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
135 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
136 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
jtgafb833d1999-08-19 00:55:39 +0000137
138 xrot = 30.0;
139 yrot = 50.0;
140 spin = 0.0;
141
jtgafb833d1999-08-19 00:55:39 +0000142 glShadeModel( GL_FLAT );
143
144 glEnable( GL_LIGHT0 );
145 glEnable( GL_LIGHTING );
146
147 glClearColor( 0.5, 0.5, 0.9, 1.0 );
148
149 glEnable( GL_NORMALIZE );
150}
151
152
153
154static void reshape(int w, int h)
155{
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000156 GLfloat yAspect = 2.5;
157 GLfloat xAspect = yAspect * (float) w / (float) h;
158 Width = w;
159 Height = h;
jtgafb833d1999-08-19 00:55:39 +0000160 glViewport(0, 0, w, h);
161 glMatrixMode(GL_PROJECTION);
162 glLoadIdentity();
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000163 glFrustum( -xAspect, xAspect, -yAspect, yAspect, 10.0, 30.0 );
jtgafb833d1999-08-19 00:55:39 +0000164 glMatrixMode(GL_MODELVIEW);
165 glLoadIdentity();
166}
167
168
169
170static void draw_objects( GLfloat eyex, GLfloat eyey, GLfloat eyez )
171{
172 (void) eyex;
173 (void) eyey;
174 (void) eyez;
175#ifndef USE_ZBUFFER
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000176 if (eyex<0.5) {
jtgafb833d1999-08-19 00:55:39 +0000177#endif
178 glPushMatrix();
179 glTranslatef( 1.0, 1.5, 0.0 );
180 glRotatef( spin, 1.0, 0.5, 0.0 );
181 glRotatef( 0.5*spin, 0.0, 0.5, 1.0 );
182 glCallList( objects_list[0] );
183 glPopMatrix();
184
185 glPushMatrix();
186 glTranslatef( -1.0, 0.85+3.0*fabs( cos(0.01*spin) ), 0.0 );
187 glRotatef( 0.5*spin, 0.0, 0.5, 1.0 );
188 glRotatef( spin, 1.0, 0.5, 0.0 );
189 glScalef( 0.5, 0.5, 0.5 );
190 glCallList( objects_list[1] );
191 glPopMatrix();
192#ifndef USE_ZBUFFER
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000193 }
194 else {
jtgafb833d1999-08-19 00:55:39 +0000195 glPushMatrix();
196 glTranslatef( -1.0, 0.85+3.0*fabs( cos(0.01*spin) ), 0.0 );
197 glRotatef( 0.5*spin, 0.0, 0.5, 1.0 );
198 glRotatef( spin, 1.0, 0.5, 0.0 );
199 glScalef( 0.5, 0.5, 0.5 );
200 glCallList( objects_list[1] );
201 glPopMatrix();
202
203 glPushMatrix();
204 glTranslatef( 1.0, 1.5, 0.0 );
205 glRotatef( spin, 1.0, 0.5, 0.0 );
206 glRotatef( 0.5*spin, 0.0, 0.5, 1.0 );
207 glCallList( objects_list[0] );
208 glPopMatrix();
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000209 }
jtgafb833d1999-08-19 00:55:39 +0000210#endif
211}
212
213
214
215static void draw_table( void )
216{
217 glCallList( table_list );
218}
219
220
221
222static void draw_scene( void )
223{
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000224 static GLfloat light_pos[] = { 0.0, 20.0, 0.0, 1.0 };
jtgafb833d1999-08-19 00:55:39 +0000225 GLfloat dist = 20.0;
226 GLfloat eyex, eyey, eyez;
227
228 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
229
230
231 eyex = dist * cos(yrot*DEG2RAD) * cos(xrot*DEG2RAD);
232 eyez = dist * sin(yrot*DEG2RAD) * cos(xrot*DEG2RAD);
233 eyey = dist * sin(xrot*DEG2RAD);
234
235 /* view from top */
236 glPushMatrix();
237 gluLookAt( eyex, eyey, eyez, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 );
238
239 glLightfv( GL_LIGHT0, GL_POSITION, light_pos );
240
241 /* draw table into stencil planes */
jtgafb833d1999-08-19 00:55:39 +0000242 glDisable( GL_DEPTH_TEST );
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000243 glEnable( GL_STENCIL_TEST );
jtgafb833d1999-08-19 00:55:39 +0000244 glStencilFunc( GL_ALWAYS, 1, 0xffffffff );
245 glStencilOp( GL_REPLACE, GL_REPLACE, GL_REPLACE );
246 glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
247 draw_table();
248 glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
249
jtgafb833d1999-08-19 00:55:39 +0000250 glEnable( GL_DEPTH_TEST );
jtgafb833d1999-08-19 00:55:39 +0000251
252 /* render view from below (reflected viewport) */
253 /* only draw where stencil==1 */
254 if (eyey>0.0) {
255 glPushMatrix();
256
257 glStencilFunc( GL_EQUAL, 1, 0xffffffff ); /* draw if ==1 */
258 glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
259 glScalef( 1.0, -1.0, 1.0 );
260
261 /* Reposition light in reflected space. */
262 glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
263
264 draw_objects(eyex, eyey, eyez);
265 glPopMatrix();
266
267 /* Restore light's original unreflected position. */
268 glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
269 }
270
271 glDisable( GL_STENCIL_TEST );
272
273 glEnable( GL_BLEND );
274 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
275
jtgafb833d1999-08-19 00:55:39 +0000276 glEnable( GL_TEXTURE_2D );
jtgafb833d1999-08-19 00:55:39 +0000277 draw_table();
278 glDisable( GL_TEXTURE_2D );
279 glDisable( GL_BLEND );
280
281 /* view from top */
282 glPushMatrix();
283
284 draw_objects(eyex, eyey, eyez);
285
286 glPopMatrix();
287
288 glPopMatrix();
289
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000290 if (ShowBuffer == GL_DEPTH) {
291 ShowDepthBuffer(Width, Height, 1.0, 0.0);
292 }
293 else if (ShowBuffer == GL_STENCIL) {
294 ShowStencilBuffer(Width, Height, 255.0, 0.0);
295 }
jtgafb833d1999-08-19 00:55:39 +0000296
297 glutSwapBuffers();
298}
jtgafb833d1999-08-19 00:55:39 +0000299
300
301static void Key( unsigned char key, int x, int y )
302{
303 (void) x;
304 (void) y;
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000305 if (key == 'd') {
306 ShowBuffer = GL_DEPTH;
307 }
308 else if (key == 's') {
309 ShowBuffer = GL_STENCIL;
310 }
311 else if (key==27) {
jtgafb833d1999-08-19 00:55:39 +0000312 exit(0);
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000313 }
314 else {
315 ShowBuffer = GL_NONE;
316 }
317 glutPostRedisplay();
jtgafb833d1999-08-19 00:55:39 +0000318}
319
320
321static void SpecialKey( int key, int x, int y )
322{
323 (void) x;
324 (void) y;
325 switch (key) {
326 case GLUT_KEY_UP:
327 xrot += 3.0;
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000328 if ( xrot > 85 )
329 xrot = 85;
jtgafb833d1999-08-19 00:55:39 +0000330 break;
331 case GLUT_KEY_DOWN:
332 xrot -= 3.0;
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000333 if ( xrot < 5 )
334 xrot = 5;
jtgafb833d1999-08-19 00:55:39 +0000335 break;
336 case GLUT_KEY_LEFT:
337 yrot += 3.0;
338 break;
339 case GLUT_KEY_RIGHT:
340 yrot -= 3.0;
341 break;
342 }
343 glutPostRedisplay();
344}
345
346
347
348static void idle( void )
349{
350 spin += 2.0;
351 yrot += 3.0;
352 glutPostRedisplay();
353}
354
355
356
357int main( int argc, char *argv[] )
358{
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000359 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH | GLUT_STENCIL);
jtgafb833d1999-08-19 00:55:39 +0000360 glutInitWindowPosition( 0, 0 );
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000361 glutInitWindowSize( Width, Height );
jtgafb833d1999-08-19 00:55:39 +0000362 glutCreateWindow(argv[0]);
363 glutReshapeFunc(reshape);
364 glutDisplayFunc(draw_scene);
365 glutKeyboardFunc(Key);
366 glutSpecialFunc(SpecialKey);
367 glutIdleFunc(idle);
jtgafb833d1999-08-19 00:55:39 +0000368 init();
jtgafb833d1999-08-19 00:55:39 +0000369 glutMainLoop();
370 return 0;
371}