2
* Demo of a reflective, texture-mapped surface with OpenGL.
3
* Brian Paul August 14, 1995 This file is in the public domain.
5
* Hardware texture mapping is highly recommended!
8
* 1. Render the reflective object (a polygon) from the normal viewpoint,
9
* setting the stencil planes = 1.
10
* 2. Render the scene from a special viewpoint: the viewpoint which
11
* is on the opposite side of the reflective plane. Only draw where
12
* stencil = 1. This draws the objects in the reflective surface.
13
* 3. Render the scene from the original viewpoint. This draws the
14
* objects in the normal fashion. Use blending when drawing
15
* the reflective, textured surface.
17
* This is a very crude demo. It could be much better.
23
* Dirk Reiners (reiners@igd.fhg.de) made some modifications to this code.
24
* Mark Kilgard (April 1997)
25
* Brian Paul (April 2000 - added keyboard d/s options)
26
* Brian Paul (August 2005 - added multi window feature)
35
#include "showbuffer.h"
39
#define DEG2RAD (3.14159/180.0)
40
#define TABLE_TEXTURE "../images/tile.rgb"
42
#define INIT_WIDTH 400
43
#define INIT_HEIGHT 300
50
int id; /* returned by glutCreateWindow() */
58
GLuint objects_list[MAX_OBJECTS];
64
static struct window *FirstWindow = NULL;
71
static struct window *
74
int id = glutGetWindow();
76
for (w = FirstWindow; w; w = w->next) {
88
for (w = FirstWindow; w; w = w->next) {
97
KillWindow(struct window *w)
99
struct window *win, *prev = NULL;
100
for (win = FirstWindow; win; win = win->next) {
103
prev->next = win->next;
106
FirstWindow = win->next;
108
glutDestroyWindow(win->id);
122
KillWindow(FirstWindow);
129
static GLfloat table_mat[] = { 1.0, 1.0, 1.0, 0.6 };
130
static GLfloat gray[] = { 0.4, 0.4, 0.4, 1.0 };
133
table_list = glGenLists(1);
134
glNewList( table_list, GL_COMPILE );
136
/* load table's texture */
137
glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, table_mat );
138
/*glMaterialfv( GL_FRONT, GL_EMISSION, gray );*/
139
glMaterialfv( GL_FRONT, GL_DIFFUSE, table_mat );
140
glMaterialfv( GL_FRONT, GL_AMBIENT, gray );
142
/* draw textured square for the table */
144
glScalef( 4.0, 4.0, 4.0 );
145
glBegin( GL_POLYGON );
146
glNormal3f( 0.0, 1.0, 0.0 );
147
glTexCoord2f( 0.0, 0.0 ); glVertex3f( -1.0, 0.0, 1.0 );
148
glTexCoord2f( 1.0, 0.0 ); glVertex3f( 1.0, 0.0, 1.0 );
149
glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 0.0, -1.0 );
150
glTexCoord2f( 0.0, 1.0 ); glVertex3f( -1.0, 0.0, -1.0 );
154
glDisable( GL_TEXTURE_2D );
162
MakeObjects(GLuint *objects_list)
166
static GLfloat cyan[] = { 0.0, 1.0, 1.0, 1.0 };
167
static GLfloat green[] = { 0.2, 1.0, 0.2, 1.0 };
168
static GLfloat black[] = { 0.0, 0.0, 0.0, 0.0 };
171
gluQuadricDrawStyle( q, GLU_FILL );
172
gluQuadricNormals( q, GLU_SMOOTH );
174
objects_list[0] = glGenLists(1);
175
glNewList( objects_list[0], GL_COMPILE );
176
glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, cyan );
177
glMaterialfv( GL_FRONT, GL_EMISSION, black );
178
gluCylinder( q, 0.5, 0.5, 1.0, 15, 1 );
181
objects_list[1] = glGenLists(1);
182
glNewList( objects_list[1], GL_COMPILE );
183
glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green );
184
glMaterialfv( GL_FRONT, GL_EMISSION, black );
185
gluCylinder( q, 1.5, 0.0, 2.5, 15, 1 );
193
InitWindow(struct window *w)
195
GLint imgWidth, imgHeight;
197
GLubyte *image = NULL;
199
w->table_list = MakeTable();
200
MakeObjects(w->objects_list);
202
image = LoadRGBImage( TABLE_TEXTURE, &imgWidth, &imgHeight, &imgFormat );
204
printf("Couldn't read %s\n", TABLE_TEXTURE);
208
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, imgWidth, imgHeight,
209
imgFormat, GL_UNSIGNED_BYTE, image);
212
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
213
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
214
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
215
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
217
glShadeModel( GL_FLAT );
219
glEnable( GL_LIGHT0 );
220
glEnable( GL_LIGHTING );
222
glClearColor( 0.5, 0.5, 0.9, 0.0 );
224
glEnable( GL_NORMALIZE );
229
Reshape(int width, int height)
231
struct window *w = CurrentWindow();
232
GLfloat yAspect = 2.5;
233
GLfloat xAspect = yAspect * (float) width / (float) height;
236
glViewport(0, 0, width, height);
237
glMatrixMode(GL_PROJECTION);
239
glFrustum( -xAspect, xAspect, -yAspect, yAspect, 10.0, 30.0 );
240
glMatrixMode(GL_MODELVIEW);
246
DrawObjects(struct window *w, GLfloat eyex, GLfloat eyey, GLfloat eyez)
255
glTranslatef( 1.0, 1.5, 0.0 );
256
glRotatef( w->spin, 1.0, 0.5, 0.0 );
257
glRotatef( 0.5*w->spin, 0.0, 0.5, 1.0 );
258
glCallList( w->objects_list[0] );
262
glTranslatef( -1.0, 0.85+3.0*fabs( cos(0.01*w->spin) ), 0.0 );
263
glRotatef( 0.5*w->spin, 0.0, 0.5, 1.0 );
264
glRotatef( w->spin, 1.0, 0.5, 0.0 );
265
glScalef( 0.5, 0.5, 0.5 );
266
glCallList( w->objects_list[1] );
272
glTranslatef( -1.0, 0.85+3.0*fabs( cos(0.01*w->spin) ), 0.0 );
273
glRotatef( 0.5*w->spin, 0.0, 0.5, 1.0 );
274
glRotatef( w->spin, 1.0, 0.5, 0.0 );
275
glScalef( 0.5, 0.5, 0.5 );
276
glCallList( w->objects_list[1] );
280
glTranslatef( 1.0, 1.5, 0.0 );
281
glRotatef( w->spin, 1.0, 0.5, 0.0 );
282
glRotatef( 0.5*w->spin, 0.0, 0.5, 1.0 );
283
glCallList( w->objects_list[0] );
291
DrawTable(struct window *w)
293
glCallList(w->table_list);
300
struct window *w = CurrentWindow();
301
static GLfloat light_pos[] = { 0.0, 20.0, 0.0, 1.0 };
303
GLfloat eyex, eyey, eyez;
305
if (w->drawBuffer == GL_NONE) {
306
glDrawBuffer(GL_BACK);
307
glReadBuffer(GL_BACK);
310
glDrawBuffer(w->drawBuffer);
311
glReadBuffer(w->drawBuffer);
314
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
316
if (w->drawBuffer == GL_NONE) {
317
glDrawBuffer(GL_NONE);
320
eyex = dist * cos(w->yrot * DEG2RAD) * cos(w->xrot * DEG2RAD);
321
eyez = dist * sin(w->yrot * DEG2RAD) * cos(w->xrot * DEG2RAD);
322
eyey = dist * sin(w->xrot * DEG2RAD);
326
gluLookAt( eyex, eyey, eyez, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 );
328
glLightfv( GL_LIGHT0, GL_POSITION, light_pos );
330
/* draw table into stencil planes */
331
glDisable( GL_DEPTH_TEST );
332
glEnable( GL_STENCIL_TEST );
333
glStencilFunc( GL_ALWAYS, 1, 0xffffffff );
334
glStencilOp( GL_REPLACE, GL_REPLACE, GL_REPLACE );
335
glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
337
glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
339
glEnable( GL_DEPTH_TEST );
341
/* render view from below (reflected viewport) */
342
/* only draw where stencil==1 */
346
glStencilFunc( GL_EQUAL, 1, 0xffffffff ); /* draw if ==1 */
347
glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
348
glScalef( 1.0, -1.0, 1.0 );
350
/* Reposition light in reflected space. */
351
glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
353
DrawObjects(w, eyex, eyey, eyez);
356
/* Restore light's original unreflected position. */
357
glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
360
glDisable( GL_STENCIL_TEST );
362
glEnable( GL_BLEND );
363
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
365
glEnable( GL_TEXTURE_2D );
367
glDisable( GL_TEXTURE_2D );
368
glDisable( GL_BLEND );
373
DrawObjects(w, eyex, eyey, eyez);
379
if (w->showBuffer == GL_DEPTH) {
380
ShowDepthBuffer(w->width, w->height, 1.0, 0.0);
382
else if (w->showBuffer == GL_STENCIL) {
383
ShowStencilBuffer(w->width, w->height, 255.0, 0.0);
385
else if (w->showBuffer == GL_ALPHA) {
386
ShowAlphaBuffer(w->width, w->height);
389
if (w->drawBuffer == GL_FRONT)
394
/* calc/show frame rate */
397
static GLint frames = 0;
398
GLint t = glutGet(GLUT_ELAPSED_TIME);
400
if (t - t0 >= 5000) {
401
GLfloat seconds = (t - t0) / 1000.0;
402
GLfloat fps = frames / seconds;
403
printf("%d frames in %g seconds = %g FPS\n", frames, seconds, fps);
415
double t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
417
for (w = FirstWindow; w; w = w->next) {
424
w->spin += 60.0 * dt;
425
w->yrot += 90.0 * dt;
427
glutSetWindow(w->id);
444
Key(unsigned char key, int x, int y)
446
struct window *w = CurrentWindow();
452
w->showBuffer = GL_DEPTH;
456
w->showBuffer = GL_STENCIL;
460
w->showBuffer = GL_ALPHA;
464
w->showBuffer = GL_NONE;
468
if (w->drawBuffer == GL_FRONT)
469
w->drawBuffer = GL_BACK;
471
w->drawBuffer = GL_FRONT;
475
w->drawBuffer = GL_NONE;
490
if (FirstWindow == NULL)
504
SpecialKey(int key, int x, int y)
506
struct window *w = CurrentWindow();
535
struct window *w = (struct window *) calloc(1, sizeof(struct window));
537
glutInitWindowSize(INIT_WIDTH, INIT_HEIGHT);
538
w->id = glutCreateWindow("foo");
539
sprintf(title, "reflect window %d", w->id);
540
glutSetWindowTitle(title);
542
w->width = INIT_WIDTH;
543
w->height = INIT_HEIGHT;
548
w->showBuffer = GL_NONE;
549
w->drawBuffer = GL_BACK;
553
glutReshapeFunc(Reshape);
554
glutDisplayFunc(DrawWindow);
555
glutKeyboardFunc(Key);
556
glutSpecialFunc(SpecialKey);
558
/* insert at head of list */
559
w->next = FirstWindow;
568
printf(" a - show alpha buffer\n");
569
printf(" d - show depth buffer\n");
570
printf(" s - show stencil buffer\n");
571
printf(" c - show color buffer\n");
572
printf(" f - toggle rendering to front/back color buffer\n");
573
printf(" n - create new window\n");
574
printf(" k - kill window\n");
575
printf(" SPACE - toggle animation\n");
576
printf(" ARROWS - rotate scene\n");
581
main(int argc, char *argv[])
583
glutInit(&argc, argv);
584
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH |
585
GLUT_STENCIL | GLUT_ALPHA);