blob: b574f43acd3d5329a2a36bf0660ad3ad9b76d799 [file] [log] [blame]
Brian Paulf02a5f62002-07-12 15:54:01 +00001/* $Id: shadowtex.c,v 1.7 2002/07/12 15:54:02 brianp Exp $ */
Brian Paul1399d762001-02-20 16:43:50 +00002
3/*
Brian Paulf204c9d2002-02-16 14:54:18 +00004 * Shadow demo using the GL_ARB_depth_texture, GL_ARB_shadow and
5 * GL_ARB_shadow_ambient extensions (or the old SGIX extensions).
Brian Paul1399d762001-02-20 16:43:50 +00006 *
7 * Brian Paul
8 * 19 Feb 2001
9 *
Brian Paul3c70f6f2002-03-23 16:34:18 +000010 * Added GL_EXT_shadow_funcs support on 23 March 2002
11 *
Brian Paul1399d762001-02-20 16:43:50 +000012 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
13 *
14 * Permission is hereby granted, free of charge, to any person obtaining a
15 * copy of this software and associated documentation files (the "Software"),
16 * to deal in the Software without restriction, including without limitation
17 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 * and/or sell copies of the Software, and to permit persons to whom the
19 * Software is furnished to do so, subject to the following conditions:
20 *
21 * The above copyright notice and this permission notice shall be included
22 * in all copies or substantial portions of the Software.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
28 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 */
31
32
Brian Paul0221e4d2001-02-28 18:41:50 +000033#include <assert.h>
Brian Paul1399d762001-02-20 16:43:50 +000034#include <stdio.h>
35#include <stdlib.h>
36#include <math.h>
37#include <GL/glut.h>
38#include "../util/showbuffer.c"
39
Brian Paulf204c9d2002-02-16 14:54:18 +000040#if 0 /* change to 1 if you want to use the old SGIX extensions */
41#undef GL_ARB_depth_texture
42#undef GL_ARB_shadow
43#undef GL_ARB_shadow_ambient
44#endif
45
Brian Paul1399d762001-02-20 16:43:50 +000046
47#define DEG_TO_RAD (3.14159 / 180.0)
48
49static GLint WindowWidth = 450, WindowHeight = 300;
50static GLfloat Xrot = 15, Yrot = 0, Zrot = 0;
51
52static GLfloat Red[4] = {1, 0, 0, 1};
53static GLfloat Green[4] = {0, 1, 0, 1};
54static GLfloat Blue[4] = {0, 0, 1, 1};
55static GLfloat Yellow[4] = {1, 1, 0, 1};
56
57static GLfloat LightDist = 10;
58static GLfloat LightLatitude = 45.0;
59static GLfloat LightLongitude = 45.0;
60static GLfloat LightPos[4];
61static GLfloat SpotDir[3];
62static GLfloat SpotAngle = 40.0 * DEG_TO_RAD;
63static GLfloat ShadowNear = 4.0, ShadowFar = 24.0;
64static GLint ShadowTexWidth = 256, ShadowTexHeight = 256;
65
Brian Paul511378b2001-02-26 18:26:32 +000066static GLboolean LinearFilter = GL_FALSE;
Brian Paul1399d762001-02-20 16:43:50 +000067
Brian Paul1399d762001-02-20 16:43:50 +000068static GLfloat Bias = -0.06;
69
70static GLboolean Anim = GL_TRUE;
71
Brian Paul3c70f6f2002-03-23 16:34:18 +000072static GLboolean HaveEXTshadowFuncs = GL_FALSE;
73static GLint Operator = 0;
74static const GLenum OperatorFunc[8] = {
75 GL_LEQUAL, GL_LESS, GL_GEQUAL, GL_GREATER,
76 GL_EQUAL, GL_NOTEQUAL, GL_ALWAYS, GL_NEVER };
77static const char *OperatorName[8] = {
78 "GL_LEQUAL", "GL_LESS", "GL_GEQUAL", "GL_GREATER",
79 "GL_EQUAL", "GL_NOTEQUAL", "GL_ALWAYS", "GL_NEVER" };
80
81
Brian Paul0221e4d2001-02-28 18:41:50 +000082static GLuint DisplayMode;
83#define SHOW_NORMAL 0
84#define SHOW_DEPTH_IMAGE 1
85#define SHOW_DEPTH_MAPPING 2
86#define SHOW_DISTANCE 3
87
88
Brian Paul1399d762001-02-20 16:43:50 +000089
90static void
91DrawScene(void)
92{
93 GLfloat k = 6;
94 /* sphere */
95 glPushMatrix();
96 glTranslatef(1.6, 2.2, 2.7);
97 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Green);
98 glColor4fv(Green);
99 glutSolidSphere(1.5, 15, 15);
100 glPopMatrix();
101 /* dodecahedron */
102 glPushMatrix();
103 glTranslatef(-2.0, 1.2, 2.1);
104 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Red);
105 glColor4fv(Red);
106 glutSolidDodecahedron();
107 glPopMatrix();
108 /* icosahedron */
109 glPushMatrix();
110 glTranslatef(-0.6, 1.3, -0.5);
111 glScalef(1.5, 1.5, 1.5);
112 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Yellow);
113 glColor4fv(Red);
114 glutSolidIcosahedron();
115 glPopMatrix();
116 /* a plane */
117 glPushMatrix();
118 glTranslatef(0, -1.1, 0);
119 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Blue);
120 glColor4fv(Blue);
121 glNormal3f(0, 1, 0);
122 glBegin(GL_POLYGON);
123 glVertex3f(-k, 0, -k);
124 glVertex3f( k, 0, -k);
125 glVertex3f( k, 0, k);
126 glVertex3f(-k, 0, k);
127 glEnd();
128 glPopMatrix();
129}
130
131
132/*
133 * Load the GL_TEXTURE matrix with the projection from the light
134 * source's point of view.
135 */
136static void
Brian Paul0221e4d2001-02-28 18:41:50 +0000137MakeShadowMatrix(const GLfloat lightPos[4], const GLfloat spotDir[3],
138 GLfloat spotAngle, GLfloat shadowNear, GLfloat shadowFar)
Brian Paul1399d762001-02-20 16:43:50 +0000139{
140 GLfloat d;
141
142 glMatrixMode(GL_TEXTURE);
143 glLoadIdentity();
144 glTranslatef(0.5, 0.5, 0.5 + Bias);
145 glScalef(0.5, 0.5, 0.5);
146 d = shadowNear * tan(spotAngle);
147 glFrustum(-d, d, -d, d, shadowNear, shadowFar);
148 gluLookAt(lightPos[0], lightPos[1], lightPos[2],
149 lightPos[0] + spotDir[0],
150 lightPos[1] + spotDir[1],
151 lightPos[2] + spotDir[2],
152 0, 1, 0);
153 glMatrixMode(GL_MODELVIEW);
154}
155
156
157static void
Brian Paul0221e4d2001-02-28 18:41:50 +0000158EnableIdentityTexgen(void)
Brian Paul1399d762001-02-20 16:43:50 +0000159{
160 /* texgen so that texcoord = vertex coord */
161 static GLfloat sPlane[4] = { 1, 0, 0, 0 };
162 static GLfloat tPlane[4] = { 0, 1, 0, 0 };
163 static GLfloat rPlane[4] = { 0, 0, 1, 0 };
164 static GLfloat qPlane[4] = { 0, 0, 0, 1 };
165
166 glTexGenfv(GL_S, GL_EYE_PLANE, sPlane);
167 glTexGenfv(GL_T, GL_EYE_PLANE, tPlane);
168 glTexGenfv(GL_R, GL_EYE_PLANE, rPlane);
169 glTexGenfv(GL_Q, GL_EYE_PLANE, qPlane);
170 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
171 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
172 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
173 glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
174
175 glEnable(GL_TEXTURE_GEN_S);
176 glEnable(GL_TEXTURE_GEN_T);
177 glEnable(GL_TEXTURE_GEN_R);
178 glEnable(GL_TEXTURE_GEN_Q);
179}
180
181
Brian Paul0221e4d2001-02-28 18:41:50 +0000182/*
183 * Setup 1-D texgen so that the distance from the light source, between
184 * the near and far planes maps to s=0 and s=1. When we draw the scene,
185 * the grayness will indicate the fragment's distance from the light
186 * source.
187 */
188static void
189EnableDistanceTexgen(const GLfloat lightPos[4], const GLfloat lightDir[3],
190 GLfloat lightNear, GLfloat lightFar)
191{
192 GLfloat m, d;
193 GLfloat sPlane[4];
194 GLfloat nearPoint[3];
195
196 m = sqrt(lightDir[0] * lightDir[0] +
197 lightDir[1] * lightDir[1] +
198 lightDir[2] * lightDir[2]);
199
200 d = lightFar - lightNear;
201
202 /* nearPoint = point on light direction vector which intersects the
203 * near plane of the light frustum.
204 */
205 nearPoint[0] = LightPos[0] + lightDir[0] / m * lightNear;
206 nearPoint[1] = LightPos[1] + lightDir[1] / m * lightNear;
207 nearPoint[2] = LightPos[2] + lightDir[2] / m * lightNear;
208
209 sPlane[0] = lightDir[0] / d / m;
210 sPlane[1] = lightDir[1] / d / m;
211 sPlane[2] = lightDir[2] / d / m;
212 sPlane[3] = -(sPlane[0] * nearPoint[0]
213 + sPlane[1] * nearPoint[1]
214 + sPlane[2] * nearPoint[2]);
215
216 glTexGenfv(GL_S, GL_EYE_PLANE, sPlane);
217 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
218 glEnable(GL_TEXTURE_GEN_S);
219}
220
221
Brian Paul1399d762001-02-20 16:43:50 +0000222static void
223DisableTexgen(void)
224{
225 glDisable(GL_TEXTURE_GEN_S);
226 glDisable(GL_TEXTURE_GEN_T);
227 glDisable(GL_TEXTURE_GEN_R);
228 glDisable(GL_TEXTURE_GEN_Q);
229}
230
231
232static void
233ComputeLightPos(GLfloat dist, GLfloat latitude, GLfloat longitude,
234 GLfloat pos[4], GLfloat dir[3])
235{
Brian Paul0221e4d2001-02-28 18:41:50 +0000236
Brian Paul1399d762001-02-20 16:43:50 +0000237 pos[0] = dist * sin(longitude * DEG_TO_RAD);
238 pos[1] = dist * sin(latitude * DEG_TO_RAD);
239 pos[2] = dist * cos(latitude * DEG_TO_RAD) * cos(longitude * DEG_TO_RAD);
240 pos[3] = 1;
241 dir[0] = -pos[0];
242 dir[1] = -pos[1];
243 dir[2] = -pos[2];
244}
245
246
247static void
248Display(void)
249{
250 GLfloat ar = (GLfloat) WindowWidth / (GLfloat) WindowHeight;
251 GLfloat d;
Brian Paul3c70f6f2002-03-23 16:34:18 +0000252 GLenum error;
Brian Paul1399d762001-02-20 16:43:50 +0000253
254 ComputeLightPos(LightDist, LightLatitude, LightLongitude,
255 LightPos, SpotDir);
256 /*
257 * Step 1: render scene from point of view of the light source
258 */
259 /* compute frustum to enclose spot light cone */
260 d = ShadowNear * tan(SpotAngle);
261 glMatrixMode(GL_PROJECTION);
262 glLoadIdentity();
263 glFrustum(-d, d, -d, d, ShadowNear, ShadowFar);
264 glMatrixMode(GL_MODELVIEW);
265 glLoadIdentity();
266 gluLookAt(LightPos[0], LightPos[1], LightPos[2], /* from */
267 0, 0, 0, /* target */
268 0, 1, 0); /* up */
269
270 glViewport(0, 0, ShadowTexWidth, ShadowTexHeight);
271 glClear(GL_DEPTH_BUFFER_BIT);
272 DrawScene();
273
274 /*
275 * Step 2: copy depth buffer into texture map
276 */
Brian Paul0221e4d2001-02-28 18:41:50 +0000277 if (DisplayMode == SHOW_DEPTH_MAPPING) {
278 /* load depth image as gray-scale luminance texture */
Brian Paulf02a5f62002-07-12 15:54:01 +0000279 GLfloat *depth = (GLfloat *) malloc(ShadowTexWidth * ShadowTexHeight
280 * sizeof(GLfloat));
Brian Paul0221e4d2001-02-28 18:41:50 +0000281 if (depth) {
282 glReadPixels(0, 0, ShadowTexWidth, ShadowTexHeight,
283 GL_DEPTH_COMPONENT, GL_FLOAT, depth);
284 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE,
285 ShadowTexWidth, ShadowTexHeight, 0,
286 GL_LUMINANCE, GL_FLOAT, depth);
287 free(depth);
288 }
289 }
290 else {
291 /* The normal shadow case */
292 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT,
293 0, 0, ShadowTexWidth, ShadowTexHeight, 0);
294 }
Brian Paul1399d762001-02-20 16:43:50 +0000295
296 /*
297 * Step 3: render scene from point of view of the camera
298 */
299 glViewport(0, 0, WindowWidth, WindowHeight);
Brian Paul0221e4d2001-02-28 18:41:50 +0000300 if (DisplayMode == SHOW_DEPTH_IMAGE) {
301 ShowDepthBuffer(WindowWidth, WindowHeight, 0, 1);
Brian Paul1399d762001-02-20 16:43:50 +0000302 }
303 else {
Brian Paul511378b2001-02-26 18:26:32 +0000304 glMatrixMode(GL_PROJECTION);
305 glLoadIdentity();
306 glFrustum(-ar, ar, -1.0, 1.0, 4.0, 50.0);
307 glMatrixMode(GL_MODELVIEW);
308 glLoadIdentity();
309 glTranslatef(0.0, 0.0, -22.0);
310 glRotatef(Xrot, 1, 0, 0);
311 glRotatef(Yrot, 0, 1, 0);
312 glRotatef(Zrot, 0, 0, 1);
Brian Paul1399d762001-02-20 16:43:50 +0000313 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
314 glLightfv(GL_LIGHT0, GL_POSITION, LightPos);
Brian Paul511378b2001-02-26 18:26:32 +0000315 if (LinearFilter) {
316 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
317 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
318 }
319 else {
320 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
321 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
322 }
Brian Paul0221e4d2001-02-28 18:41:50 +0000323 if (DisplayMode == SHOW_DEPTH_MAPPING) {
Brian Paulf204c9d2002-02-16 14:54:18 +0000324#if defined(GL_ARB_shadow)
325 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
326#elif defined(GL_SGIX_shadow)
Brian Paul0221e4d2001-02-28 18:41:50 +0000327 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_SGIX, GL_FALSE);
Brian Paulf204c9d2002-02-16 14:54:18 +0000328#endif
Brian Paul0221e4d2001-02-28 18:41:50 +0000329 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
330 glEnable(GL_TEXTURE_2D);
331 MakeShadowMatrix(LightPos, SpotDir, SpotAngle, ShadowNear, ShadowFar);
332 EnableIdentityTexgen();
333 }
334 else if (DisplayMode == SHOW_DISTANCE) {
335 glMatrixMode(GL_TEXTURE);
336 glLoadIdentity();
337 glMatrixMode(GL_MODELVIEW);
338 EnableDistanceTexgen(LightPos, SpotDir, ShadowNear+Bias, ShadowFar);
339 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
340 glEnable(GL_TEXTURE_1D);
341 }
342 else {
343 assert(DisplayMode == SHOW_NORMAL);
Brian Paulf204c9d2002-02-16 14:54:18 +0000344#if defined(GL_ARB_shadow)
345 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB,
346 GL_COMPARE_R_TO_TEXTURE_ARB);
347#elif defined(GL_SGIX_shadow)
Brian Paul0221e4d2001-02-28 18:41:50 +0000348 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_SGIX, GL_TRUE);
Brian Paulf204c9d2002-02-16 14:54:18 +0000349#endif
Brian Paul0221e4d2001-02-28 18:41:50 +0000350 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
351 glEnable(GL_TEXTURE_2D);
352 MakeShadowMatrix(LightPos, SpotDir, SpotAngle, ShadowNear, ShadowFar);
353 EnableIdentityTexgen();
354 }
Brian Paul1399d762001-02-20 16:43:50 +0000355 DrawScene();
356 DisableTexgen();
Brian Paul0221e4d2001-02-28 18:41:50 +0000357 glDisable(GL_TEXTURE_1D);
Brian Paul1399d762001-02-20 16:43:50 +0000358 glDisable(GL_TEXTURE_2D);
359 }
360
361 glutSwapBuffers();
Brian Paul3c70f6f2002-03-23 16:34:18 +0000362
363 error = glGetError();
364 if (error) {
365 printf("GL Error: %s\n", gluErrorString(error));
366 }
Brian Paul1399d762001-02-20 16:43:50 +0000367}
368
369
370static void
371Reshape(int width, int height)
372{
373 WindowWidth = width;
374 WindowHeight = height;
Brian Paul511378b2001-02-26 18:26:32 +0000375 if (width >= 512 && height >= 512) {
376 ShadowTexWidth = ShadowTexHeight = 512;
377 }
378 else if (width >= 256 && height >= 256) {
379 ShadowTexWidth = ShadowTexHeight = 256;
380 }
381 else {
382 ShadowTexWidth = ShadowTexHeight = 128;
383 }
384 printf("Using %d x %d depth texture\n", ShadowTexWidth, ShadowTexHeight);
Brian Paul1399d762001-02-20 16:43:50 +0000385}
386
387
388static void
389Idle(void)
390{
391 Yrot += 5.0;
392 /*LightLongitude -= 5.0;*/
393 glutPostRedisplay();
394}
395
396
397static void
398Key(unsigned char key, int x, int y)
399{
400 const GLfloat step = 3.0;
401 (void) x;
402 (void) y;
403 switch (key) {
404 case 'a':
405 Anim = !Anim;
406 if (Anim)
407 glutIdleFunc(Idle);
408 else
409 glutIdleFunc(NULL);
410 break;
411 case 'b':
412 Bias -= 0.01;
Brian Paul511378b2001-02-26 18:26:32 +0000413 printf("Bias %g\n", Bias);
Brian Paul1399d762001-02-20 16:43:50 +0000414 break;
415 case 'B':
416 Bias += 0.01;
Brian Paul511378b2001-02-26 18:26:32 +0000417 printf("Bias %g\n", Bias);
Brian Paul1399d762001-02-20 16:43:50 +0000418 break;
419 case 'd':
Brian Paul0221e4d2001-02-28 18:41:50 +0000420 DisplayMode = SHOW_DISTANCE;
Brian Paul1399d762001-02-20 16:43:50 +0000421 break;
Brian Paul511378b2001-02-26 18:26:32 +0000422 case 'f':
423 LinearFilter = !LinearFilter;
424 printf("%s filtering\n", LinearFilter ? "Bilinear" : "Nearest");
425 break;
Brian Paul0221e4d2001-02-28 18:41:50 +0000426 case 'i':
427 DisplayMode = SHOW_DEPTH_IMAGE;
428 break;
429 case 'm':
430 DisplayMode = SHOW_DEPTH_MAPPING;
431 break;
432 case 'n':
433 case ' ':
434 DisplayMode = SHOW_NORMAL;
435 break;
Brian Paul3c70f6f2002-03-23 16:34:18 +0000436 case 'o':
437 if (HaveEXTshadowFuncs) {
438 Operator++;
439 if (Operator >= 8)
440 Operator = 0;
441 printf("Operator: %s\n", OperatorName[Operator]);
442 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB,
443 OperatorFunc[Operator]);
444 }
445 break;
Brian Paul1399d762001-02-20 16:43:50 +0000446 case 'z':
447 Zrot -= step;
448 break;
449 case 'Z':
450 Zrot += step;
451 break;
452 case 27:
453 exit(0);
454 break;
455 }
456 glutPostRedisplay();
Brian Paul1399d762001-02-20 16:43:50 +0000457}
458
459
460static void
461SpecialKey(int key, int x, int y)
462{
463 const GLfloat step = 3.0;
464 const int mod = glutGetModifiers();
465 (void) x;
466 (void) y;
467 switch (key) {
468 case GLUT_KEY_UP:
469 if (mod)
470 LightLatitude += step;
471 else
472 Xrot += step;
473 break;
474 case GLUT_KEY_DOWN:
475 if (mod)
476 LightLatitude -= step;
477 else
478 Xrot -= step;
479 break;
480 case GLUT_KEY_LEFT:
481 if (mod)
482 LightLongitude += step;
483 else
484 Yrot += step;
485 break;
486 case GLUT_KEY_RIGHT:
487 if (mod)
488 LightLongitude -= step;
489 else
490 Yrot -= step;
491 break;
492 }
493 glutPostRedisplay();
494}
495
496
497static void
498Init(void)
499{
Brian Paulf204c9d2002-02-16 14:54:18 +0000500#if defined(GL_ARB_depth_texture) && defined(GL_ARB_shadow)
501 if (!glutExtensionSupported("GL_ARB_depth_texture") ||
502 !glutExtensionSupported("GL_ARB_shadow")) {
503 printf("Sorry, this demo requires the GL_ARB_depth_texture and GL_ARB_shadow extensions\n");
504 exit(1);
505 }
506 printf("Using GL_ARB_depth_texture and GL_ARB_shadow\n");
507#elif defined(GL_SGIX_depth_texture) && defined(GL_SGIX_shadow)
Brian Paul1399d762001-02-20 16:43:50 +0000508 if (!glutExtensionSupported("GL_SGIX_depth_texture") ||
509 !glutExtensionSupported("GL_SGIX_shadow")) {
510 printf("Sorry, this demo requires the GL_SGIX_depth_texture and GL_SGIX_shadow extensions\n");
511 exit(1);
512 }
Brian Paulf204c9d2002-02-16 14:54:18 +0000513 printf("Using GL_SGIX_depth_texture and GL_SGIX_shadow\n");
514#endif
Brian Paul3c70f6f2002-03-23 16:34:18 +0000515 HaveEXTshadowFuncs = glutExtensionSupported("GL_EXT_shadow_funcs");
Brian Paul1399d762001-02-20 16:43:50 +0000516
Brian Paul0221e4d2001-02-28 18:41:50 +0000517 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP);
518 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
519 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
520 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP);
Brian Paul1399d762001-02-20 16:43:50 +0000521 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
522 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
Brian Paulf204c9d2002-02-16 14:54:18 +0000523#if defined(GL_ARB_shadow)
524 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB,
525 GL_COMPARE_R_TO_TEXTURE_ARB);
526 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
527#elif defined(GL_SGIX_shadow)
Brian Paul1399d762001-02-20 16:43:50 +0000528 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_OPERATOR_SGIX,
529 GL_TEXTURE_LEQUAL_R_SGIX);
Brian Paul0a0595f2001-02-20 17:06:35 +0000530#endif
Brian Paulf204c9d2002-02-16 14:54:18 +0000531
532#if defined(GL_ARB_shadow_ambient)
533 if (glutExtensionSupported("GL_ARB_shadow_ambient")) {
534 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FAIL_VALUE_ARB, 0.3);
535 printf("and GL_ARB_shadow_ambient\n");
536 }
537#elif defined(GL_SGIX_shadow_ambient)
538 if (glutExtensionSupported("GL_SGIX_shadow_ambient")) {
Brian Paul1399d762001-02-20 16:43:50 +0000539 glTexParameterf(GL_TEXTURE_2D, GL_SHADOW_AMBIENT_SGIX, 0.3);
Brian Paulf204c9d2002-02-16 14:54:18 +0000540 printf("and GL_SGIX_shadow_ambient\n");
541 }
Brian Paul0a0595f2001-02-20 17:06:35 +0000542#endif
Brian Paul1399d762001-02-20 16:43:50 +0000543
Brian Paul0221e4d2001-02-28 18:41:50 +0000544 /* setup 1-D grayscale texture image for SHOW_DISTANCE mode */
545 {
546 GLuint i;
547 GLubyte image[256];
548 for (i = 0; i < 256; i++)
549 image[i] = i;
550 glTexImage1D(GL_TEXTURE_1D, 0, GL_LUMINANCE,
551 256, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, image);
552 }
553
Brian Paul1399d762001-02-20 16:43:50 +0000554 glEnable(GL_DEPTH_TEST);
555 glEnable(GL_LIGHTING);
556 glEnable(GL_LIGHT0);
557}
558
559
560static void
561PrintHelp(void)
562{
563 printf("Keys:\n");
564 printf(" a = toggle animation\n");
Brian Paul0221e4d2001-02-28 18:41:50 +0000565 printf(" i = show depth texture image\n");
566 printf(" m = show depth texture mapping\n");
567 printf(" d = show fragment distance from light source\n");
568 printf(" n = show normal, shadowed image\n");
Brian Paul511378b2001-02-26 18:26:32 +0000569 printf(" f = toggle nearest/bilinear texture filtering\n");
Brian Paul1399d762001-02-20 16:43:50 +0000570 printf(" b/B = decrease/increase shadow map Z bias\n");
571 printf(" cursor keys = rotate scene\n");
572 printf(" <shift> + cursor keys = rotate light source\n");
Brian Paul3c70f6f2002-03-23 16:34:18 +0000573 if (HaveEXTshadowFuncs)
574 printf(" o = cycle through comparison modes\n");
Brian Paul1399d762001-02-20 16:43:50 +0000575}
576
577
578int
579main(int argc, char *argv[])
580{
581 glutInit(&argc, argv);
582 glutInitWindowPosition(0, 0);
583 glutInitWindowSize(WindowWidth, WindowHeight);
584 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
585 glutCreateWindow(argv[0]);
586 glutReshapeFunc(Reshape);
587 glutKeyboardFunc(Key);
588 glutSpecialFunc(SpecialKey);
589 glutDisplayFunc(Display);
590 if (Anim)
591 glutIdleFunc(Idle);
592 Init();
593 PrintHelp();
594 glutMainLoop();
595 return 0;
596}