Merge branch '7.8'
[mesa.git] / progs / redbook / shadowmap.c
1 /*
2 * Copyright (c) 1993-2003, Silicon Graphics, Inc.
3 * All Rights Reserved
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose and without fee is hereby granted, provided that the above
7 * copyright notice appear in all copies and that both the copyright
8 * notice and this permission notice appear in supporting documentation,
9 * and that the name of Silicon Graphics, Inc. not be used in
10 * advertising or publicity pertaining to distribution of the software
11 * without specific, written prior permission.
12 *
13 * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS" AND
14 * WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
16 * FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
17 * GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
18 * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
19 * OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION, LOSS OF
20 * PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF THIRD
21 * PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN ADVISED OF
22 * THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON ANY THEORY OF
23 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE POSSESSION, USE
24 * OR PERFORMANCE OF THIS SOFTWARE.
25 *
26 * US Government Users Restricted Rights
27 * Use, duplication, or disclosure by the Government is subject to
28 * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
29 * (c)(1)(ii) of the Rights in Technical Data and Computer Software
30 * clause at DFARS 252.227-7013 and/or in similar or successor clauses
31 * in the FAR or the DOD or NASA FAR Supplement. Unpublished - rights
32 * reserved under the copyright laws of the United States.
33 *
34 * Contractor/manufacturer is:
35 * Silicon Graphics, Inc.
36 * 1500 Crittenden Lane
37 * Mountain View, CA 94043
38 * United State of America
39 *
40 * OpenGL(R) is a registered trademark of Silicon Graphics, Inc.
41 */
42
43 #include <math.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <GL/glew.h>
47 #include <GL/glut.h>
48 /*#include "helpers.h"*/
49
50 #define SHADOW_MAP_WIDTH 256
51 #define SHADOW_MAP_HEIGHT 256
52
53 #define PI 3.14159265359
54
55 GLdouble fovy = 60.0;
56 GLdouble nearPlane = 10.0;
57 GLdouble farPlane = 100.0;
58
59 GLfloat angle = 0.0;
60 GLfloat torusAngle = 0.0;
61
62 GLfloat lightPos[] = { 25.0, 25.0, 25.0, 1.0 };
63 GLfloat lookat[] = { 0.0, 0.0, 0.0 };
64 GLfloat up[] = { 0.0, 0.0, 1.0 };
65
66 GLboolean showShadow = GL_FALSE;
67
68 static void
69 init( void )
70 {
71 GLfloat white[] = { 1.0, 1.0, 1.0, 1.0 };
72
73 glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT,
74 SHADOW_MAP_WIDTH, SHADOW_MAP_HEIGHT, 0,
75 GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL );
76
77 glLightfv( GL_LIGHT0, GL_POSITION, lightPos );
78 glLightfv( GL_LIGHT0, GL_SPECULAR, white );
79 glLightfv( GL_LIGHT0, GL_DIFFUSE, white );
80
81 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
82 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
83 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
84 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
85 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL );
86 glTexParameteri( GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE );
87 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE,
88 GL_COMPARE_R_TO_TEXTURE );
89
90 glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
91 glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
92 glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
93 glTexGeni( GL_Q, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
94
95 glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
96
97 glCullFace( GL_BACK );
98
99 glEnable( GL_DEPTH_TEST );
100 glEnable( GL_LIGHT0 );
101 glEnable( GL_LIGHTING );
102 glEnable( GL_TEXTURE_2D );
103 glEnable( GL_TEXTURE_GEN_S );
104 glEnable( GL_TEXTURE_GEN_T );
105 glEnable( GL_TEXTURE_GEN_R );
106 glEnable( GL_TEXTURE_GEN_Q );
107 glEnable( GL_COLOR_MATERIAL );
108 glEnable( GL_CULL_FACE );
109 }
110
111 static void
112 reshape( int width, int height )
113 {
114 glViewport( 0, 0, width, height );
115
116 glMatrixMode( GL_PROJECTION );
117 glLoadIdentity();
118 gluPerspective( fovy, (GLdouble) width/height, nearPlane, farPlane );
119 glMatrixMode( GL_MODELVIEW );
120 }
121
122 static void
123 idle( void )
124 {
125 angle += PI / 10000;
126 torusAngle += .1;
127 glutPostRedisplay();
128 }
129
130 static void
131 keyboard( unsigned char key, int x, int y )
132 {
133 switch( key ) {
134 case 27: /* Escape */
135 exit( 0 );
136 break;
137
138 case 't': {
139 static GLboolean textureOn = GL_TRUE;
140 textureOn = !textureOn;
141 if ( textureOn )
142 glEnable( GL_TEXTURE_2D );
143 else
144 glDisable( GL_TEXTURE_2D );
145 }
146 break;
147
148 case 'm': {
149 static GLboolean compareMode = GL_TRUE;
150 compareMode = !compareMode;
151 printf( "Compare mode %s\n", compareMode ? "On" : "Off" );
152 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE,
153 compareMode ? GL_COMPARE_R_TO_TEXTURE : GL_NONE );
154 }
155 break;
156
157 case 'f': {
158 static GLboolean funcMode = GL_TRUE;
159 funcMode = !funcMode;
160 printf( "Operator %s\n", funcMode ? "GL_LEQUAL" : "GL_GEQUAL" );
161 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC,
162 funcMode ? GL_LEQUAL : GL_GEQUAL );
163 }
164 break;
165
166 case 's':
167 showShadow = !showShadow;
168 break;
169
170 case 'p': {
171 static GLboolean animate = GL_TRUE;
172 animate = !animate;
173 glutIdleFunc( animate ? idle : NULL );
174 }
175 break;
176 }
177
178 glutPostRedisplay();
179 }
180
181 static void
182 transposeMatrix( GLfloat m[16] )
183 {
184 GLfloat tmp;
185 #define Swap( a, b ) tmp = a; a = b; b = tmp
186 Swap( m[1], m[4] );
187 Swap( m[2], m[8] );
188 Swap( m[3], m[12] );
189 Swap( m[6], m[9] );
190 Swap( m[7], m[13] );
191 Swap( m[11], m[14] );
192 #undef Swap
193 }
194
195 static void
196 drawObjects( GLboolean shadowRender )
197 {
198 GLboolean textureOn = glIsEnabled( GL_TEXTURE_2D );
199
200 if ( shadowRender )
201 glDisable( GL_TEXTURE_2D );
202
203 if ( !shadowRender ) {
204 glNormal3f( 0, 0, 1 );
205 glColor3f( 1, 1, 1 );
206 glRectf( -20.0, -20.0, 20.0, 20.0 );
207 }
208
209 glPushMatrix();
210 glTranslatef( 11, 11, 11 );
211 glRotatef( 54.73, -5, 5, 0 );
212 glRotatef( torusAngle, 1, 0, 0 );
213 glColor3f( 1, 0, 0 );
214 glutSolidTorus( 1, 4, 8, 36 );
215 glPopMatrix();
216
217 glPushMatrix();
218 glTranslatef( 2, 2, 2 );
219 glColor3f( 0, 0, 1 );
220 glutSolidCube( 4 );
221 glPopMatrix();
222
223 glPushMatrix();
224 glTranslatef( lightPos[0], lightPos[1], lightPos[2] );
225 glColor3f( 1, 1, 1 );
226 glutWireSphere( 0.5, 6, 6 );
227 glPopMatrix();
228
229 if ( shadowRender && textureOn )
230 glEnable( GL_TEXTURE_2D );
231 }
232
233 static void
234 generateShadowMap( void )
235 {
236 GLint viewport[4];
237 GLfloat lightPos[4];
238
239 glGetLightfv( GL_LIGHT0, GL_POSITION, lightPos );
240 glGetIntegerv( GL_VIEWPORT, viewport );
241
242 glViewport( 0, 0, SHADOW_MAP_WIDTH, SHADOW_MAP_HEIGHT );
243
244 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
245
246 glMatrixMode( GL_PROJECTION );
247 glPushMatrix();
248 glLoadIdentity();
249 gluPerspective( 80.0, 1.0, 10.0, 1000.0 );
250 glMatrixMode( GL_MODELVIEW );
251
252 glPushMatrix();
253 glLoadIdentity();
254 gluLookAt( lightPos[0], lightPos[1], lightPos[2],
255 lookat[0], lookat[1], lookat[2],
256 up[0], up[1], up[2] );
257
258 drawObjects( GL_TRUE );
259
260 glPopMatrix();
261 glMatrixMode( GL_PROJECTION );
262 glPopMatrix();
263 glMatrixMode( GL_MODELVIEW );
264
265 glCopyTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 0, 0,
266 SHADOW_MAP_WIDTH, SHADOW_MAP_HEIGHT, 0 );
267
268 glViewport( viewport[0], viewport[1], viewport[2], viewport[3] );
269
270 if ( showShadow ) {
271 GLfloat depthImage[SHADOW_MAP_WIDTH][SHADOW_MAP_HEIGHT];
272 glReadPixels( 0, 0, SHADOW_MAP_WIDTH, SHADOW_MAP_HEIGHT,
273 GL_DEPTH_COMPONENT, GL_FLOAT, depthImage );
274 glWindowPos2f( viewport[2]/2, 0 );
275 glDrawPixels( SHADOW_MAP_WIDTH, SHADOW_MAP_HEIGHT, GL_LUMINANCE,
276 GL_FLOAT, depthImage );
277 glutSwapBuffers();
278 }
279 }
280
281 static void
282 generateTextureMatrix( void )
283 {
284 GLfloat tmpMatrix[16];
285
286 /*
287 * Set up projective texture matrix. We use the GL_MODELVIEW matrix
288 * stack and OpenGL matrix commands to make the matrix.
289 */
290 glPushMatrix();
291 glLoadIdentity();
292 glTranslatef( 0.5, 0.5, 0.0 );
293 glScalef( 0.5, 0.5, 1.0 );
294 gluPerspective( 60.0, 1.0, 1.0, 1000.0 );
295 gluLookAt( lightPos[0], lightPos[1], lightPos[2],
296 lookat[0], lookat[1], lookat[2],
297 up[0], up[1], up[2] );
298 glGetFloatv( GL_MODELVIEW_MATRIX, tmpMatrix );
299 glPopMatrix();
300
301 transposeMatrix( tmpMatrix );
302
303 glTexGenfv( GL_S, GL_OBJECT_PLANE, &tmpMatrix[0] );
304 glTexGenfv( GL_T, GL_OBJECT_PLANE, &tmpMatrix[4] );
305 glTexGenfv( GL_R, GL_OBJECT_PLANE, &tmpMatrix[8] );
306 glTexGenfv( GL_Q, GL_OBJECT_PLANE, &tmpMatrix[12] );
307 }
308
309 static void
310 display( void )
311 {
312 GLfloat radius = 30;
313
314 generateShadowMap();
315 generateTextureMatrix();
316
317 if ( showShadow )
318 return;
319
320 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
321
322 glPushMatrix();
323 gluLookAt( radius*cos(angle), radius*sin(angle), 30,
324 lookat[0], lookat[1], lookat[2],
325 up[0], up[1], up[2] );
326 drawObjects( GL_FALSE );
327 glPopMatrix();
328
329 glutSwapBuffers();
330 }
331
332 int
333 main( int argc, char** argv )
334 {
335 glutInit( &argc, argv );
336 glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );
337 glutInitWindowSize( 512, 512 );
338 glutInitWindowPosition( 100, 100 );
339 glutCreateWindow( argv[0] );
340 glewInit();
341
342 init();
343
344 glutDisplayFunc( display );
345 glutReshapeFunc( reshape );
346 glutKeyboardFunc( keyboard );
347 glutIdleFunc( idle );
348
349 glutMainLoop();
350
351 return 0;
352 }