3 * Demo of a reflective, texture-mapped surface with OpenGL.
4 * Brian Paul August 14, 1995 This file is in the public domain.
6 * Hardware texture mapping is highly recommended!
9 * 1. Render the reflective object (a polygon) from the normal viewpoint,
10 * setting the stencil planes = 1.
11 * 2. Render the scene from a special viewpoint: the viewpoint which
12 * is on the opposite side of the reflective plane. Only draw where
13 * stencil = 1. This draws the objects in the reflective surface.
14 * 3. Render the scene from the original viewpoint. This draws the
15 * objects in the normal fashion. Use blending when drawing
16 * the reflective, textured surface.
18 * This is a very crude demo. It could be much better.
24 * Dirk Reiners (reiners@igd.fhg.de) made some modifications to this code.
25 * Mark Kilgard (April 1997)
26 * Brian Paul (April 2000 - added keyboard d/s options)
34 #include "showbuffer.h"
38 #define DEG2RAD (3.14159/180.0)
40 #define TABLE_TEXTURE "../images/tile.rgb"
42 static GLint ImgWidth
, ImgHeight
;
43 static GLenum ImgFormat
;
44 static GLubyte
*Image
= NULL
;
47 static GLint table_list
;
48 static GLint objects_list
[MAX_OBJECTS
];
50 static GLfloat xrot
, yrot
;
53 static GLint Width
= 400, Height
= 300;
54 static GLenum ShowBuffer
= GL_NONE
;
55 static GLboolean Anim
= GL_TRUE
;
57 /* performance info */
59 static GLint Frames
= 0;
62 static void make_table( void )
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 };
67 table_list
= glGenLists(1);
68 glNewList( table_list
, GL_COMPILE
);
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
);
76 /* draw textured square for the table */
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 );
88 glDisable( GL_TEXTURE_2D
);
94 static void make_objects( void )
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 };
103 gluQuadricDrawStyle( q
, GLU_FILL
);
104 gluQuadricNormals( q
, GLU_SMOOTH
);
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 );
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 );
122 static void init( void )
127 Image
= LoadRGBImage( TABLE_TEXTURE
, &ImgWidth
, &ImgHeight
, &ImgFormat
);
129 printf("Couldn't read %s\n", TABLE_TEXTURE
);
133 gluBuild2DMipmaps(GL_TEXTURE_2D
, 3, ImgWidth
, ImgHeight
,
134 ImgFormat
, GL_UNSIGNED_BYTE
, Image
);
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
);
145 glShadeModel( GL_FLAT
);
147 glEnable( GL_LIGHT0
);
148 glEnable( GL_LIGHTING
);
150 glClearColor( 0.5, 0.5, 0.9, 0.0 );
152 glEnable( GL_NORMALIZE
);
157 static void reshape(int w
, int h
)
159 GLfloat yAspect
= 2.5;
160 GLfloat xAspect
= yAspect
* (float) w
/ (float) h
;
163 glViewport(0, 0, w
, h
);
164 glMatrixMode(GL_PROJECTION
);
166 glFrustum( -xAspect
, xAspect
, -yAspect
, yAspect
, 10.0, 30.0 );
167 glMatrixMode(GL_MODELVIEW
);
173 static void draw_objects( GLfloat eyex
, GLfloat eyey
, GLfloat eyez
)
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] );
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] );
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] );
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] );
218 static void draw_table( void )
220 glCallList( table_list
);
225 static void draw_scene( void )
227 static GLfloat light_pos
[] = { 0.0, 20.0, 0.0, 1.0 };
229 GLfloat eyex
, eyey
, eyez
;
231 glClear( GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
234 eyex
= dist
* cos(yrot
*DEG2RAD
) * cos(xrot
*DEG2RAD
);
235 eyez
= dist
* sin(yrot
*DEG2RAD
) * cos(xrot
*DEG2RAD
);
236 eyey
= dist
* sin(xrot
*DEG2RAD
);
240 gluLookAt( eyex
, eyey
, eyez
, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 );
242 glLightfv( GL_LIGHT0
, GL_POSITION
, light_pos
);
244 /* draw table into stencil planes */
245 glDisable( GL_DEPTH_TEST
);
246 glEnable( GL_STENCIL_TEST
);
247 glStencilFunc( GL_ALWAYS
, 1, 0xffffffff );
248 glStencilOp( GL_REPLACE
, GL_REPLACE
, GL_REPLACE
);
249 glColorMask( GL_FALSE
, GL_FALSE
, GL_FALSE
, GL_FALSE
);
251 glColorMask( GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
253 glEnable( GL_DEPTH_TEST
);
255 /* render view from below (reflected viewport) */
256 /* only draw where stencil==1 */
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 );
264 /* Reposition light in reflected space. */
265 glLightfv(GL_LIGHT0
, GL_POSITION
, light_pos
);
267 draw_objects(eyex
, eyey
, eyez
);
270 /* Restore light's original unreflected position. */
271 glLightfv(GL_LIGHT0
, GL_POSITION
, light_pos
);
274 glDisable( GL_STENCIL_TEST
);
276 glEnable( GL_BLEND
);
277 glBlendFunc( GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
279 glEnable( GL_TEXTURE_2D
);
281 glDisable( GL_TEXTURE_2D
);
282 glDisable( GL_BLEND
);
287 draw_objects(eyex
, eyey
, eyez
);
293 if (ShowBuffer
== GL_DEPTH
) {
294 ShowDepthBuffer(Width
, Height
, 1.0, 0.0);
296 else if (ShowBuffer
== GL_STENCIL
) {
297 ShowStencilBuffer(Width
, Height
, 255.0, 0.0);
299 else if (ShowBuffer
== GL_ALPHA
) {
300 ShowAlphaBuffer(Width
, Height
);
306 GLint t
= glutGet(GLUT_ELAPSED_TIME
);
308 if (t
- T0
>= 5000) {
309 GLfloat seconds
= (t
- T0
) / 1000.0;
310 GLfloat fps
= Frames
/ seconds
;
311 printf("%d frames in %g seconds = %g FPS\n", Frames
, seconds
, fps
);
319 static void idle( void )
321 static double t0
= -1.;
322 double dt
, t
= glutGet(GLUT_ELAPSED_TIME
) / 1000.0;
333 static void Key( unsigned char key
, int x
, int y
)
338 ShowBuffer
= GL_DEPTH
;
340 else if (key
== 's') {
341 ShowBuffer
= GL_STENCIL
;
343 else if (key
== 'a') {
344 ShowBuffer
= GL_ALPHA
;
346 else if (key
== ' ') {
357 ShowBuffer
= GL_NONE
;
363 static void SpecialKey( int key
, int x
, int y
)
389 int main( int argc
, char *argv
[] )
391 glutInit(&argc
, argv
);
392 glutInitDisplayMode(GLUT_DOUBLE
| GLUT_RGB
| GLUT_DEPTH
| GLUT_STENCIL
| GLUT_ALPHA
);
393 glutInitWindowPosition( 0, 0 );
394 glutInitWindowSize( Width
, Height
);
395 glutCreateWindow(argv
[0]);
396 glutReshapeFunc(reshape
);
397 glutDisplayFunc(draw_scene
);
398 glutKeyboardFunc(Key
);
399 glutSpecialFunc(SpecialKey
);