2 * Shadow demo using the GL_ARB_depth_texture, GL_ARB_shadow and
3 * GL_ARB_shadow_ambient extensions.
8 * Added GL_EXT_shadow_funcs support on 23 March 2002
9 * Added GL_EXT_packed_depth_stencil support on 15 March 2006.
10 * Added GL_EXT_framebuffer_object support on 27 March 2006.
11 * Removed old SGIX extension support on 5 April 2006.
12 * Added vertex / fragment program support on 7 June 2007 (Ian Romanick).
14 * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
16 * Permission is hereby granted, free of charge, to any person obtaining a
17 * copy of this software and associated documentation files (the "Software"),
18 * to deal in the Software without restriction, including without limitation
19 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
20 * and/or sell copies of the Software, and to permit persons to whom the
21 * Software is furnished to do so, subject to the following conditions:
23 * The above copyright notice and this permission notice shall be included
24 * in all copies or substantial portions of the Software.
26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
27 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
29 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
30 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 #define GL_GLEXT_PROTOTYPES
41 #include "showbuffer.h"
43 #define DEG_TO_RAD (3.14159 / 180.0)
45 static GLint WindowWidth
= 450, WindowHeight
= 300;
46 static GLfloat Xrot
= 15, Yrot
= 0, Zrot
= 0;
48 static GLfloat Red
[4] = {1, 0, 0, 1};
49 static GLfloat Green
[4] = {0, 1, 0, 1};
50 static GLfloat Blue
[4] = {0, 0, 1, 1};
51 static GLfloat Yellow
[4] = {1, 1, 0, 1};
53 static GLfloat LightDist
= 10;
54 static GLfloat LightLatitude
= 45.0;
55 static GLfloat LightLongitude
= 45.0;
56 static GLfloat LightPos
[4];
57 static GLfloat SpotDir
[3];
58 static GLfloat SpotAngle
= 40.0 * DEG_TO_RAD
;
59 static GLfloat ShadowNear
= 4.0, ShadowFar
= 24.0;
60 static GLint ShadowTexWidth
= 256, ShadowTexHeight
= 256;
62 static GLboolean LinearFilter
= GL_FALSE
;
64 static GLfloat Bias
= -0.06;
66 static GLboolean Anim
= GL_TRUE
;
68 static GLboolean NeedNewShadowMap
= GL_FALSE
;
69 static GLuint ShadowTexture
, GrayTexture
;
70 static GLuint ShadowFBO
;
72 static GLfloat lightModelview
[16];
73 static GLfloat lightProjection
[16];
75 static GLuint vert_prog
;
76 static GLuint frag_progs
[3];
77 static GLuint curr_frag
= 0;
78 static GLuint max_frag
= 1;
80 #define NUM_FRAG_MODES 3
81 static const char *FragProgNames
[] = {
83 "program without \"OPTION ARB_fragment_program_shadow\"",
84 "program with \"OPTION ARB_fragment_program_shadow\"",
87 static GLboolean HaveShadow
= GL_FALSE
;
88 static GLboolean HaveFBO
= GL_FALSE
;
89 static GLboolean UseFBO
= GL_FALSE
;
90 static GLboolean HaveVP
= GL_FALSE
;
91 static GLboolean HaveFP
= GL_FALSE
;
92 static GLboolean HaveFP_Shadow
= GL_FALSE
;
93 static GLboolean UseVP
= GL_FALSE
;
94 static GLboolean HavePackedDepthStencil
= GL_FALSE
;
95 static GLboolean UsePackedDepthStencil
= GL_FALSE
;
96 static GLboolean HaveEXTshadowFuncs
= GL_FALSE
;
97 static GLboolean HaveShadowAmbient
= GL_FALSE
;
99 static GLint Operator
= 0;
100 static const GLenum OperatorFunc
[8] = {
101 GL_LEQUAL
, GL_LESS
, GL_GEQUAL
, GL_GREATER
,
102 GL_EQUAL
, GL_NOTEQUAL
, GL_ALWAYS
, GL_NEVER
};
103 static const char *OperatorName
[8] = {
104 "GL_LEQUAL", "GL_LESS", "GL_GEQUAL", "GL_GREATER",
105 "GL_EQUAL", "GL_NOTEQUAL", "GL_ALWAYS", "GL_NEVER" };
108 static GLuint DisplayMode
;
109 #define SHOW_SHADOWS 0
110 #define SHOW_DEPTH_IMAGE 1
111 #define SHOW_DEPTH_MAPPING 2
112 #define SHOW_DISTANCE 3
116 #define MAT4_MUL(dest_vec, src_mat, src_vec) \
117 "DP4 " dest_vec ".x, " src_mat "[0], " src_vec ";\n" \
118 "DP4 " dest_vec ".y, " src_mat "[1], " src_vec ";\n" \
119 "DP4 " dest_vec ".z, " src_mat "[2], " src_vec ";\n" \
120 "DP4 " dest_vec ".w, " src_mat "[3], " src_vec ";\n"
122 #define MAT3_MUL(dest_vec, src_mat, src_vec) \
123 "DP3 " dest_vec ".x, " src_mat "[0], " src_vec ";\n" \
124 "DP3 " dest_vec ".y, " src_mat "[1], " src_vec ";\n" \
125 "DP3 " dest_vec ".z, " src_mat "[2], " src_vec ";\n"
127 #define NORMALIZE(dest, src) \
128 "DP3 " dest ".w, " src ", " src ";\n" \
129 "RSQ " dest ".w, " dest ".w;\n" \
130 "MUL " dest ", " src ", " dest ".w;\n"
133 * Vertex program for shadow mapping.
135 static const char vert_code
[] =
137 "ATTRIB iPos = vertex.position;\n"
138 "ATTRIB iNorm = vertex.normal;\n"
140 "PARAM mvinv[4] = { state.matrix.modelview.invtrans };\n"
141 "PARAM mvp[4] = { state.matrix.mvp };\n"
142 "PARAM mv[4] = { state.matrix.modelview };\n"
143 "PARAM texmat[4] = { state.matrix.texture[0] };\n"
144 "PARAM lightPos = state.light[0].position;\n"
145 "PARAM ambientCol = state.lightprod[0].ambient;\n"
146 "PARAM diffuseCol = state.lightprod[0].diffuse;\n"
148 "TEMP n, lightVec;\n"
149 "ALIAS V = lightVec;\n"
152 "OUTPUT oPos = result.position;\n"
153 "OUTPUT oColor = result.color;\n"
154 "OUTPUT oTex = result.texcoord[0];\n"
156 /* Transform the vertex to clip coordinates. */
157 MAT4_MUL("oPos", "mvp", "iPos")
159 /* Transform the vertex to eye coordinates. */
160 MAT4_MUL("V", "mv", "iPos")
162 /* Transform the vertex to projected light coordinates. */
163 MAT4_MUL("oTex", "texmat", "iPos")
165 /* Transform the normal to eye coordinates. */
166 MAT3_MUL("n", "mvinv", "iNorm")
168 /* Calculate the vector from the vertex to the light in eye
171 "SUB lightVec, lightPos, V;\n"
172 NORMALIZE("lightVec", "lightVec")
174 /* Compute diffuse lighting coefficient.
176 "DP3 NdotL.x, n, lightVec;\n"
177 "MAX NdotL.x, NdotL.x, {0.0};\n"
178 "MIN NdotL.x, NdotL.x, {1.0};\n"
180 /* Accumulate color contributions.
182 "MOV oColor, diffuseCol;\n"
183 "MAD oColor.xyz, NdotL.x, diffuseCol, ambientCol;\n"
187 static const char frag_code
[] =
190 "TEMP shadow, temp;\n"
192 "TXP shadow, fragment.texcoord[0], texture[0], 2D;\n"
193 "RCP temp.x, fragment.texcoord[0].w;\n"
194 "MUL temp.x, temp.x, fragment.texcoord[0].z;\n"
195 "SGE shadow, shadow.x, temp.x;\n"
196 "MUL result.color.rgb, fragment.color, shadow.x;\n"
197 "MOV result.color.a, fragment.color;\n"
201 static const char frag_shadow_code
[] =
203 "OPTION ARB_fragment_program_shadow;\n"
207 "TXP shadow, fragment.texcoord[0], texture[0], SHADOW2D;\n"
208 "MUL result.color.rgb, fragment.color, shadow.x;\n"
209 "MOV result.color.a, fragment.color.a;\n"
220 glTranslatef(1.6, 2.2, 2.7);
221 glMaterialfv(GL_FRONT_AND_BACK
, GL_AMBIENT_AND_DIFFUSE
, Green
);
223 glutSolidSphere(1.5, 15, 15);
227 glTranslatef(-2.0, 1.2, 2.1);
228 glMaterialfv(GL_FRONT_AND_BACK
, GL_AMBIENT_AND_DIFFUSE
, Red
);
230 glutSolidDodecahedron();
234 glTranslatef(-0.6, 1.3, -0.5);
235 glScalef(1.5, 1.5, 1.5);
236 glMaterialfv(GL_FRONT_AND_BACK
, GL_AMBIENT_AND_DIFFUSE
, Yellow
);
238 glutSolidIcosahedron();
242 glTranslatef(0, -1.1, 0);
243 glMaterialfv(GL_FRONT_AND_BACK
, GL_AMBIENT_AND_DIFFUSE
, Blue
);
247 glVertex3f(-k
, 0, -k
);
248 glVertex3f( k
, 0, -k
);
249 glVertex3f( k
, 0, k
);
250 glVertex3f(-k
, 0, k
);
257 * Calculate modelview and project matrices for the light
259 * Stores the results in \c lightProjection (projection matrix) and
260 * \c lightModelview (modelview matrix).
263 MakeShadowMatrix(const GLfloat lightPos
[4], const GLfloat spotDir
[3],
264 GLfloat spotAngle
, GLfloat shadowNear
, GLfloat shadowFar
)
266 /* compute frustum to enclose spot light cone */
267 const GLfloat d
= shadowNear
* tan(spotAngle
);
269 glMatrixMode(GL_PROJECTION
);
272 glFrustum(-d
, d
, -d
, d
, shadowNear
, shadowFar
);
273 glGetFloatv(GL_PROJECTION_MATRIX
, lightProjection
);
276 glMatrixMode(GL_MODELVIEW
);
279 gluLookAt(lightPos
[0], lightPos
[1], lightPos
[2],
280 lightPos
[0] + spotDir
[0],
281 lightPos
[1] + spotDir
[1],
282 lightPos
[2] + spotDir
[2],
284 glGetFloatv(GL_MODELVIEW_MATRIX
, lightModelview
);
290 * Load \c GL_TEXTURE matrix with light's MVP matrix.
292 static void SetShadowTextureMatrix(void)
294 static const GLfloat biasMatrix
[16] = {
301 glMatrixMode(GL_TEXTURE
);
302 glLoadMatrixf(biasMatrix
);
303 glTranslatef(0.0, 0.0, Bias
);
304 glMultMatrixf(lightProjection
);
305 glMultMatrixf(lightModelview
);
306 glMatrixMode(GL_MODELVIEW
);
311 EnableIdentityTexgen(void)
313 /* texgen so that texcoord = vertex coord */
314 static GLfloat sPlane
[4] = { 1, 0, 0, 0 };
315 static GLfloat tPlane
[4] = { 0, 1, 0, 0 };
316 static GLfloat rPlane
[4] = { 0, 0, 1, 0 };
317 static GLfloat qPlane
[4] = { 0, 0, 0, 1 };
319 glTexGenfv(GL_S
, GL_EYE_PLANE
, sPlane
);
320 glTexGenfv(GL_T
, GL_EYE_PLANE
, tPlane
);
321 glTexGenfv(GL_R
, GL_EYE_PLANE
, rPlane
);
322 glTexGenfv(GL_Q
, GL_EYE_PLANE
, qPlane
);
323 glTexGeni(GL_S
, GL_TEXTURE_GEN_MODE
, GL_EYE_LINEAR
);
324 glTexGeni(GL_T
, GL_TEXTURE_GEN_MODE
, GL_EYE_LINEAR
);
325 glTexGeni(GL_R
, GL_TEXTURE_GEN_MODE
, GL_EYE_LINEAR
);
326 glTexGeni(GL_Q
, GL_TEXTURE_GEN_MODE
, GL_EYE_LINEAR
);
328 glEnable(GL_TEXTURE_GEN_S
);
329 glEnable(GL_TEXTURE_GEN_T
);
330 glEnable(GL_TEXTURE_GEN_R
);
331 glEnable(GL_TEXTURE_GEN_Q
);
336 * Setup 1-D texgen so that the distance from the light source, between
337 * the near and far planes maps to s=0 and s=1. When we draw the scene,
338 * the grayness will indicate the fragment's distance from the light
342 EnableDistanceTexgen(const GLfloat lightPos
[4], const GLfloat lightDir
[3],
343 GLfloat lightNear
, GLfloat lightFar
)
347 GLfloat nearPoint
[3];
349 m
= sqrt(lightDir
[0] * lightDir
[0] +
350 lightDir
[1] * lightDir
[1] +
351 lightDir
[2] * lightDir
[2]);
353 d
= lightFar
- lightNear
;
355 /* nearPoint = point on light direction vector which intersects the
356 * near plane of the light frustum.
358 nearPoint
[0] = lightPos
[0] + lightDir
[0] / m
* lightNear
;
359 nearPoint
[1] = lightPos
[1] + lightDir
[1] / m
* lightNear
;
360 nearPoint
[2] = lightPos
[2] + lightDir
[2] / m
* lightNear
;
362 sPlane
[0] = lightDir
[0] / d
/ m
;
363 sPlane
[1] = lightDir
[1] / d
/ m
;
364 sPlane
[2] = lightDir
[2] / d
/ m
;
365 sPlane
[3] = -(sPlane
[0] * nearPoint
[0]
366 + sPlane
[1] * nearPoint
[1]
367 + sPlane
[2] * nearPoint
[2]);
369 glTexGenfv(GL_S
, GL_EYE_PLANE
, sPlane
);
370 glTexGeni(GL_S
, GL_TEXTURE_GEN_MODE
, GL_EYE_LINEAR
);
371 glEnable(GL_TEXTURE_GEN_S
);
378 glDisable(GL_TEXTURE_GEN_S
);
379 glDisable(GL_TEXTURE_GEN_T
);
380 glDisable(GL_TEXTURE_GEN_R
);
381 glDisable(GL_TEXTURE_GEN_Q
);
386 ComputeLightPos(GLfloat dist
, GLfloat latitude
, GLfloat longitude
,
387 GLfloat pos
[4], GLfloat dir
[3])
390 pos
[0] = dist
* sin(longitude
* DEG_TO_RAD
);
391 pos
[1] = dist
* sin(latitude
* DEG_TO_RAD
);
392 pos
[2] = dist
* cos(latitude
* DEG_TO_RAD
) * cos(longitude
* DEG_TO_RAD
);
401 * Render the shadow map / depth texture.
402 * The result will be in the texture object named ShadowTexture.
405 RenderShadowMap(void)
407 GLenum depthFormat
; /* GL_DEPTH_COMPONENT or GL_DEPTH_STENCIL_EXT */
408 GLenum depthType
; /* GL_UNSIGNED_INT_24_8_EXT or GL_UNSIGNED_INT */
410 if (WindowWidth
>= 1024 && WindowHeight
>= 1024) {
411 ShadowTexWidth
= ShadowTexHeight
= 1024;
413 else if (WindowWidth
>= 512 && WindowHeight
>= 512) {
414 ShadowTexWidth
= ShadowTexHeight
= 512;
416 else if (WindowWidth
>= 256 && WindowHeight
>= 256) {
417 ShadowTexWidth
= ShadowTexHeight
= 256;
420 ShadowTexWidth
= ShadowTexHeight
= 128;
422 printf("Rendering %d x %d depth texture\n", ShadowTexWidth
, ShadowTexHeight
);
424 if (UsePackedDepthStencil
) {
425 depthFormat
= GL_DEPTH_STENCIL_EXT
;
426 depthType
= GL_UNSIGNED_INT_24_8_EXT
;
429 depthFormat
= GL_DEPTH_COMPONENT
;
430 depthType
= GL_UNSIGNED_INT
;
433 glMatrixMode(GL_PROJECTION
);
434 glLoadMatrixf(lightProjection
);
436 glMatrixMode(GL_MODELVIEW
);
437 glLoadMatrixf(lightModelview
);
442 glTexImage2D(GL_TEXTURE_2D
, 0, depthFormat
,
443 ShadowTexWidth
, ShadowTexHeight
, 0,
444 depthFormat
, depthType
, NULL
);
446 /* Set the filter mode so that the texture is texture-complete.
447 * Otherwise it will cause the framebuffer to fail the framebuffer
450 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
452 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, ShadowFBO
);
453 glDrawBuffer(GL_NONE
);
454 glReadBuffer(GL_NONE
);
456 fbo_status
= glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT
);
457 if (fbo_status
!= GL_FRAMEBUFFER_COMPLETE_EXT
) {
458 fprintf(stderr
, "FBO not complete! status = 0x%04x\n", fbo_status
);
459 assert(fbo_status
== GL_FRAMEBUFFER_COMPLETE_EXT
);
463 assert(!glIsEnabled(GL_TEXTURE_1D
));
464 assert(!glIsEnabled(GL_TEXTURE_2D
));
466 glViewport(0, 0, ShadowTexWidth
, ShadowTexHeight
);
467 glClear(GL_DEPTH_BUFFER_BIT
);
468 glEnable(GL_DEPTH_TEST
);
473 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, 0);
477 * copy depth buffer into the texture map
479 if (DisplayMode
== SHOW_DEPTH_MAPPING
) {
480 /* load depth image as gray-scale luminance texture */
481 GLuint
*depth
= (GLuint
*)
482 malloc(ShadowTexWidth
* ShadowTexHeight
* sizeof(GLuint
));
484 glReadPixels(0, 0, ShadowTexWidth
, ShadowTexHeight
,
485 depthFormat
, depthType
, depth
);
486 glTexImage2D(GL_TEXTURE_2D
, 0, GL_LUMINANCE
,
487 ShadowTexWidth
, ShadowTexHeight
, 0,
488 GL_LUMINANCE
, GL_UNSIGNED_INT
, depth
);
492 /* The normal shadow case - a real depth texture */
493 glCopyTexImage2D(GL_TEXTURE_2D
, 0, depthFormat
,
494 0, 0, ShadowTexWidth
, ShadowTexHeight
, 0);
495 if (UsePackedDepthStencil
) {
498 glGetTexLevelParameteriv(GL_TEXTURE_2D
, 0,
499 GL_TEXTURE_INTERNAL_FORMAT
, &intFormat
);
500 assert(intFormat
== GL_DEPTH_STENCIL_EXT
);
508 * Show the shadow map as a grayscale image.
513 glClear(GL_COLOR_BUFFER_BIT
);
515 glMatrixMode(GL_TEXTURE
);
518 glMatrixMode(GL_PROJECTION
);
520 glOrtho(0, WindowWidth
, 0, WindowHeight
, -1, 1);
522 glMatrixMode(GL_MODELVIEW
);
525 glDisable(GL_DEPTH_TEST
);
526 glDisable(GL_LIGHTING
);
528 glEnable(GL_TEXTURE_2D
);
532 /* interpret texture's depth values as luminance values */
534 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_COMPARE_MODE_ARB
, GL_NONE
);
537 glTexParameteri(GL_TEXTURE_2D
, GL_DEPTH_TEXTURE_MODE_ARB
, GL_LUMINANCE
);
538 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_REPLACE
);
541 glTexCoord2f(0, 0); glVertex2f(0, 0);
542 glTexCoord2f(1, 0); glVertex2f(ShadowTexWidth
, 0);
543 glTexCoord2f(1, 1); glVertex2f(ShadowTexWidth
, ShadowTexHeight
);
544 glTexCoord2f(0, 1); glVertex2f(0, ShadowTexHeight
);
547 glDisable(GL_TEXTURE_2D
);
548 glEnable(GL_DEPTH_TEST
);
549 glEnable(GL_LIGHTING
);
554 * Redraw window image
561 ComputeLightPos(LightDist
, LightLatitude
, LightLongitude
,
564 if (NeedNewShadowMap
) {
565 MakeShadowMatrix(LightPos
, SpotDir
, SpotAngle
, ShadowNear
, ShadowFar
);
567 NeedNewShadowMap
= GL_FALSE
;
570 glViewport(0, 0, WindowWidth
, WindowHeight
);
571 if (DisplayMode
== SHOW_DEPTH_IMAGE
) {
575 /* prepare to draw scene from camera's view */
576 const GLfloat ar
= (GLfloat
) WindowWidth
/ (GLfloat
) WindowHeight
;
578 glMatrixMode(GL_PROJECTION
);
580 glFrustum(-ar
, ar
, -1.0, 1.0, 4.0, 50.0);
582 glMatrixMode(GL_MODELVIEW
);
584 glTranslatef(0.0, 0.0, -22.0);
585 glRotatef(Xrot
, 1, 0, 0);
586 glRotatef(Yrot
, 0, 1, 0);
587 glRotatef(Zrot
, 0, 0, 1);
589 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
591 glLightfv(GL_LIGHT0
, GL_POSITION
, LightPos
);
594 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
595 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
598 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
599 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
602 if (DisplayMode
== SHOW_DEPTH_MAPPING
) {
604 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_COMPARE_MODE_ARB
, GL_NONE
);
606 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_REPLACE
);
607 glEnable(GL_TEXTURE_2D
);
609 SetShadowTextureMatrix();
610 EnableIdentityTexgen();
612 else if (DisplayMode
== SHOW_DISTANCE
) {
613 glMatrixMode(GL_TEXTURE
);
615 glMatrixMode(GL_MODELVIEW
);
616 EnableDistanceTexgen(LightPos
, SpotDir
, ShadowNear
+Bias
, ShadowFar
);
617 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_REPLACE
);
618 glEnable(GL_TEXTURE_1D
);
619 assert(!glIsEnabled(GL_TEXTURE_2D
));
622 assert(DisplayMode
== SHOW_SHADOWS
);
624 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_COMPARE_MODE_ARB
,
625 GL_COMPARE_R_TO_TEXTURE_ARB
);
629 glEnable(GL_FRAGMENT_PROGRAM_ARB
);
632 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_MODULATE
);
634 glEnable(GL_TEXTURE_2D
);
636 SetShadowTextureMatrix();
639 glEnable(GL_VERTEX_PROGRAM_ARB
);
642 glEnable(GL_LIGHTING
);
643 EnableIdentityTexgen();
650 glDisable(GL_VERTEX_PROGRAM_ARB
);
654 glDisable(GL_LIGHTING
);
658 glDisable(GL_FRAGMENT_PROGRAM_ARB
);
661 glDisable(GL_TEXTURE_1D
);
662 glDisable(GL_TEXTURE_2D
);
667 error
= glGetError();
669 printf("GL Error: %s\n", (char *) gluErrorString(error
));
675 Reshape(int width
, int height
)
678 WindowHeight
= height
;
679 NeedNewShadowMap
= GL_TRUE
;
686 static double t0
= -1.;
687 double dt
, t
= glutGet(GLUT_ELAPSED_TIME
) / 1000.0;
693 /*LightLongitude -= 5.0;*/
699 Key(unsigned char key
, int x
, int y
)
701 const GLfloat step
= 3.0;
714 printf("Bias %g\n", Bias
);
718 printf("Bias %g\n", Bias
);
721 DisplayMode
= SHOW_DISTANCE
;
724 LinearFilter
= !LinearFilter
;
725 printf("%s filtering\n", LinearFilter
? "Bilinear" : "Nearest");
728 DisplayMode
= SHOW_DEPTH_IMAGE
;
731 DisplayMode
= SHOW_DEPTH_MAPPING
;
734 curr_frag
= (1 + curr_frag
) % max_frag
;
735 if (!HaveShadow
&& (curr_frag
== 0)) {
739 printf("Using fragment %s\n", FragProgNames
[curr_frag
]);
742 glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB
, frag_progs
[curr_frag
]);
748 DisplayMode
= SHOW_SHADOWS
;
751 if (HaveEXTshadowFuncs
) {
755 printf("Operator: %s\n", OperatorName
[Operator
]);
757 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_COMPARE_FUNC_ARB
,
758 OperatorFunc
[Operator
]);
763 UsePackedDepthStencil
= !UsePackedDepthStencil
;
764 if (UsePackedDepthStencil
&& !HavePackedDepthStencil
) {
765 printf("Sorry, GL_EXT_packed_depth_stencil not supported\n");
766 UsePackedDepthStencil
= GL_FALSE
;
769 printf("Use GL_DEPTH_STENCIL_EXT: %d\n", UsePackedDepthStencil
);
770 /* Don't really need to regenerate shadow map texture, but do so
771 * to exercise more code more often.
773 NeedNewShadowMap
= GL_TRUE
;
777 UseVP
= !UseVP
&& HaveVP
;
778 printf("Using vertex %s mode.\n",
779 UseVP
? "program" : "fixed-function");
796 SpecialKey(int key
, int x
, int y
)
798 const GLfloat step
= 3.0;
799 const int mod
= glutGetModifiers();
805 LightLatitude
+= step
;
811 LightLatitude
-= step
;
817 LightLongitude
+= step
;
823 LightLongitude
-= step
;
829 NeedNewShadowMap
= GL_TRUE
;
835 /* A helper for finding errors in program strings */
836 static int FindLine( const char *program
, int position
)
839 for (i
= 0; i
< position
; i
++) {
840 if (program
[i
] == '\n')
848 compile_program(GLenum target
, const char *code
)
854 glGenProgramsARB(1, & p
);
856 glBindProgramARB(target
, p
);
857 glProgramStringARB(target
, GL_PROGRAM_FORMAT_ASCII_ARB
,
859 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB
, &errorPos
);
860 if (glGetError() != GL_NO_ERROR
|| errorPos
!= -1) {
861 int l
= FindLine(code
, errorPos
);
862 printf("Fragment Program Error (pos=%d line=%d): %s\n", errorPos
, l
,
863 (char *) glGetString(GL_PROGRAM_ERROR_STRING_ARB
));
867 glBindProgramARB(target
, 0);
874 static const GLfloat borderColor
[4] = {1.0, 0.0, 0.0, 0.0};
876 if (!glutExtensionSupported("GL_ARB_depth_texture")) {
877 printf("Sorry, this demo requires the GL_ARB_depth_texture extension\n");
881 HaveShadow
= glutExtensionSupported("GL_ARB_shadow");
882 HaveVP
= glutExtensionSupported("GL_ARB_vertex_program");
883 HaveFP
= glutExtensionSupported("GL_ARB_fragment_program");
884 HaveFP_Shadow
= glutExtensionSupported("GL_ARB_fragment_program_shadow");
886 if (!HaveShadow
&& !HaveFP
) {
887 printf("Sorry, this demo requires either the GL_ARB_shadow extension "
888 "or the GL_ARB_fragment_program extension\n");
892 printf("Using GL_ARB_depth_texture\n");
894 printf("and GL_ARB_shadow\n");
898 printf("and GL_ARB_fragment_program\n");
901 HaveShadowAmbient
= glutExtensionSupported("GL_ARB_shadow_ambient");
902 if (HaveShadowAmbient
) {
903 printf("and GL_ARB_shadow_ambient\n");
906 HaveEXTshadowFuncs
= glutExtensionSupported("GL_EXT_shadow_funcs");
908 HavePackedDepthStencil
= glutExtensionSupported("GL_EXT_packed_depth_stencil");
909 UsePackedDepthStencil
= HavePackedDepthStencil
;
911 #if defined(GL_EXT_framebuffer_object)
912 HaveFBO
= glutExtensionSupported("GL_EXT_framebuffer_object");
915 printf("Using GL_EXT_framebuffer_object\n");
920 * Set up the 2D shadow map texture
922 glGenTextures(1, &ShadowTexture
);
923 glBindTexture(GL_TEXTURE_2D
, ShadowTexture
);
924 glTexParameterfv(GL_TEXTURE_2D
, GL_TEXTURE_BORDER_COLOR
, borderColor
);
925 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP
);
926 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP
);
929 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_COMPARE_MODE_ARB
,
930 GL_COMPARE_R_TO_TEXTURE_ARB
);
931 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_COMPARE_FUNC_ARB
, GL_LEQUAL
);
934 if (HaveShadowAmbient
) {
935 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_COMPARE_FAIL_VALUE_ARB
, 0.3);
938 #if defined(GL_EXT_framebuffer_object)
940 glGenFramebuffersEXT(1, &ShadowFBO
);
941 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, ShadowFBO
);
942 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT
,
943 GL_COLOR_ATTACHMENT0_EXT
,
944 GL_RENDERBUFFER_EXT
, 0);
945 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT
, GL_DEPTH_ATTACHMENT_EXT
,
946 GL_TEXTURE_2D
, ShadowTexture
, 0);
948 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, 0);
953 * Setup 1-D grayscale texture image for SHOW_DISTANCE mode
955 glGenTextures(1, &GrayTexture
);
956 glBindTexture(GL_TEXTURE_1D
, GrayTexture
);
957 glTexParameteri(GL_TEXTURE_1D
, GL_TEXTURE_WRAP_S
, GL_CLAMP
);
958 glTexParameteri(GL_TEXTURE_1D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
959 glTexParameteri(GL_TEXTURE_1D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
963 for (i
= 0; i
< 256; i
++)
965 glTexImage1D(GL_TEXTURE_1D
, 0, GL_LUMINANCE
,
966 256, 0, GL_LUMINANCE
, GL_UNSIGNED_BYTE
, image
);
970 vert_prog
= compile_program(GL_VERTEX_PROGRAM_ARB
, vert_code
);
971 glBindProgramARB(GL_VERTEX_PROGRAM_ARB
, vert_prog
);
978 frag_progs
[1] = compile_program(GL_FRAGMENT_PROGRAM_ARB
, frag_code
);
982 if (HaveFP
&& HaveFP_Shadow
) {
983 frag_progs
[2] = compile_program(GL_FRAGMENT_PROGRAM_ARB
,
990 glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB
, frag_progs
[curr_frag
]);
993 glEnable(GL_DEPTH_TEST
);
994 glEnable(GL_LIGHTING
);
1003 printf(" a = toggle animation\n");
1004 printf(" i = show depth texture image\n");
1005 printf(" m = show depth texture mapping\n");
1006 printf(" d = show fragment distance from light source\n");
1007 printf(" n = show normal, shadowed image\n");
1008 printf(" f = toggle nearest/bilinear texture filtering\n");
1009 printf(" b/B = decrease/increase shadow map Z bias\n");
1010 printf(" p = toggle use of packed depth/stencil\n");
1011 printf(" M = cycle through fragment program modes\n");
1012 printf(" v = toggle vertex program modes\n");
1013 printf(" cursor keys = rotate scene\n");
1014 printf(" <shift> + cursor keys = rotate light source\n");
1015 if (HaveEXTshadowFuncs
)
1016 printf(" o = cycle through comparison modes\n");
1021 main(int argc
, char *argv
[])
1023 glutInit(&argc
, argv
);
1024 glutInitWindowPosition(0, 0);
1025 glutInitWindowSize(WindowWidth
, WindowHeight
);
1026 glutInitDisplayMode(GLUT_RGB
| GLUT_DOUBLE
| GLUT_DEPTH
| GLUT_STENCIL
);
1027 glutCreateWindow(argv
[0]);
1028 glutReshapeFunc(Reshape
);
1029 glutKeyboardFunc(Key
);
1030 glutSpecialFunc(SpecialKey
);
1031 glutDisplayFunc(Display
);