1 /* $Id: reflect.c,v 1.3 2000/06/15 14:25:48 brianp Exp $ */
4 * Demo of a reflective, texture-mapped surface with OpenGL.
5 * Brian Paul August 14, 1995 This file is in the public domain.
7 * Hardware texture mapping is highly recommended!
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.
19 * This is a very crude demo. It could be much better.
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)
35 #include "../util/showbuffer.c"
36 #include "../util/readtex.c"
39 #define DEG2RAD (3.14159/180.0)
41 #define TABLE_TEXTURE "../images/tile.rgb"
43 static GLint ImgWidth
, ImgHeight
;
44 static GLenum ImgFormat
;
45 static GLubyte
*Image
= NULL
;
48 static GLint table_list
;
49 static GLint objects_list
[MAX_OBJECTS
];
51 static GLfloat xrot
, yrot
;
54 static GLint Width
= 400, Height
= 300;
55 static GLenum ShowBuffer
= GL_NONE
;
59 static void make_table( void )
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 };
64 table_list
= glGenLists(1);
65 glNewList( table_list
, GL_COMPILE
);
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
);
73 /* draw textured square for the table */
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 );
85 glDisable( GL_TEXTURE_2D
);
91 static void make_objects( void )
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 };
100 gluQuadricDrawStyle( q
, GLU_FILL
);
101 gluQuadricNormals( q
, GLU_SMOOTH
);
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 );
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 );
119 static void init( void )
124 Image
= LoadRGBImage( TABLE_TEXTURE
, &ImgWidth
, &ImgHeight
, &ImgFormat
);
126 printf("Couldn't read %s\n", TABLE_TEXTURE
);
130 gluBuild2DMipmaps(GL_TEXTURE_2D
, 3, ImgWidth
, ImgHeight
,
131 ImgFormat
, GL_UNSIGNED_BYTE
, Image
);
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
);
142 glShadeModel( GL_FLAT
);
144 glEnable( GL_LIGHT0
);
145 glEnable( GL_LIGHTING
);
147 glClearColor( 0.5, 0.5, 0.9, 1.0 );
149 glEnable( GL_NORMALIZE
);
154 static void reshape(int w
, int h
)
156 GLfloat yAspect
= 2.5;
157 GLfloat xAspect
= yAspect
* (float) w
/ (float) h
;
160 glViewport(0, 0, w
, h
);
161 glMatrixMode(GL_PROJECTION
);
163 glFrustum( -xAspect
, xAspect
, -yAspect
, yAspect
, 10.0, 30.0 );
164 glMatrixMode(GL_MODELVIEW
);
170 static void draw_objects( GLfloat eyex
, GLfloat eyey
, GLfloat eyez
)
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] );
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] );
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] );
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] );
215 static void draw_table( void )
217 glCallList( table_list
);
222 static void draw_scene( void )
224 static GLfloat light_pos
[] = { 0.0, 20.0, 0.0, 1.0 };
226 GLfloat eyex
, eyey
, eyez
;
228 glClear( GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
231 eyex
= dist
* cos(yrot
*DEG2RAD
) * cos(xrot
*DEG2RAD
);
232 eyez
= dist
* sin(yrot
*DEG2RAD
) * cos(xrot
*DEG2RAD
);
233 eyey
= dist
* sin(xrot
*DEG2RAD
);
237 gluLookAt( eyex
, eyey
, eyez
, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 );
239 glLightfv( GL_LIGHT0
, GL_POSITION
, light_pos
);
241 /* draw table into stencil planes */
242 glDisable( GL_DEPTH_TEST
);
243 glEnable( GL_STENCIL_TEST
);
244 glStencilFunc( GL_ALWAYS
, 1, 0xffffffff );
245 glStencilOp( GL_REPLACE
, GL_REPLACE
, GL_REPLACE
);
246 glColorMask( GL_FALSE
, GL_FALSE
, GL_FALSE
, GL_FALSE
);
248 glColorMask( GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
250 glEnable( GL_DEPTH_TEST
);
252 /* render view from below (reflected viewport) */
253 /* only draw where stencil==1 */
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 );
261 /* Reposition light in reflected space. */
262 glLightfv(GL_LIGHT0
, GL_POSITION
, light_pos
);
264 draw_objects(eyex
, eyey
, eyez
);
267 /* Restore light's original unreflected position. */
268 glLightfv(GL_LIGHT0
, GL_POSITION
, light_pos
);
271 glDisable( GL_STENCIL_TEST
);
273 glEnable( GL_BLEND
);
274 glBlendFunc( GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
276 glEnable( GL_TEXTURE_2D
);
278 glDisable( GL_TEXTURE_2D
);
279 glDisable( GL_BLEND
);
284 draw_objects(eyex
, eyey
, eyez
);
290 if (ShowBuffer
== GL_DEPTH
) {
291 ShowDepthBuffer(Width
, Height
, 1.0, 0.0);
293 else if (ShowBuffer
== GL_STENCIL
) {
294 ShowStencilBuffer(Width
, Height
, 255.0, 0.0);
301 static void Key( unsigned char key
, int x
, int y
)
306 ShowBuffer
= GL_DEPTH
;
308 else if (key
== 's') {
309 ShowBuffer
= GL_STENCIL
;
315 ShowBuffer
= GL_NONE
;
321 static void SpecialKey( int key
, int x
, int y
)
348 static void idle( void )
357 int main( int argc
, char *argv
[] )
359 glutInit(&argc
, argv
);
360 glutInitDisplayMode(GLUT_DOUBLE
| GLUT_RGB
| GLUT_DEPTH
| GLUT_STENCIL
);
361 glutInitWindowPosition( 0, 0 );
362 glutInitWindowSize( Width
, Height
);
363 glutCreateWindow(argv
[0]);
364 glutReshapeFunc(reshape
);
365 glutDisplayFunc(draw_scene
);
366 glutKeyboardFunc(Key
);
367 glutSpecialFunc(SpecialKey
);