132001f49Smrg/* 232001f49Smrg * Shadow demo using the GL_ARB_depth_texture, GL_ARB_shadow and 332001f49Smrg * GL_ARB_shadow_ambient extensions. 432001f49Smrg * 532001f49Smrg * Brian Paul 632001f49Smrg * 19 Feb 2001 732001f49Smrg * 832001f49Smrg * Added GL_EXT_shadow_funcs support on 23 March 2002 932001f49Smrg * Added GL_EXT_packed_depth_stencil support on 15 March 2006. 1032001f49Smrg * Added GL_EXT_framebuffer_object support on 27 March 2006. 1132001f49Smrg * Removed old SGIX extension support on 5 April 2006. 1232001f49Smrg * Added vertex / fragment program support on 7 June 2007 (Ian Romanick). 1332001f49Smrg * 1432001f49Smrg * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. 1532001f49Smrg * 1632001f49Smrg * Permission is hereby granted, free of charge, to any person obtaining a 1732001f49Smrg * copy of this software and associated documentation files (the "Software"), 1832001f49Smrg * to deal in the Software without restriction, including without limitation 1932001f49Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 2032001f49Smrg * and/or sell copies of the Software, and to permit persons to whom the 2132001f49Smrg * Software is furnished to do so, subject to the following conditions: 2232001f49Smrg * 2332001f49Smrg * The above copyright notice and this permission notice shall be included 2432001f49Smrg * in all copies or substantial portions of the Software. 2532001f49Smrg * 2632001f49Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 2732001f49Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2832001f49Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 2932001f49Smrg * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 3032001f49Smrg * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 3132001f49Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 3232001f49Smrg */ 3332001f49Smrg 3432001f49Smrg#include <assert.h> 3532001f49Smrg#include <stdio.h> 3632001f49Smrg#include <stdlib.h> 3732001f49Smrg#include <string.h> 3832001f49Smrg#include <math.h> 3932001f49Smrg#include <GL/glew.h> 4032001f49Smrg#include "glut_wrap.h" 4132001f49Smrg 4232001f49Smrg#define DEG_TO_RAD (3.14159 / 180.0) 4332001f49Smrg 4432001f49Smrgstatic GLint WindowWidth = 450, WindowHeight = 300; 4532001f49Smrgstatic GLfloat Xrot = 15, Yrot = 0, Zrot = 0; 4632001f49Smrg 4732001f49Smrgstatic GLfloat Red[4] = {1, 0, 0, 1}; 4832001f49Smrgstatic GLfloat Green[4] = {0, 1, 0, 1}; 4932001f49Smrgstatic GLfloat Blue[4] = {0, 0, 1, 1}; 5032001f49Smrgstatic GLfloat Yellow[4] = {1, 1, 0, 1}; 5132001f49Smrg 5232001f49Smrgstatic GLfloat LightDist = 10; 5332001f49Smrgstatic GLfloat LightLatitude = 45.0; 5432001f49Smrgstatic GLfloat LightLongitude = 45.0; 5532001f49Smrgstatic GLfloat LightPos[4]; 5632001f49Smrgstatic GLfloat SpotDir[3]; 5732001f49Smrgstatic GLfloat SpotAngle = 40.0 * DEG_TO_RAD; 5832001f49Smrgstatic GLfloat ShadowNear = 4.0, ShadowFar = 24.0; 5932001f49Smrgstatic GLint ShadowTexWidth = 256, ShadowTexHeight = 256; 6032001f49Smrg 6132001f49Smrgstatic GLboolean LinearFilter = GL_FALSE; 6232001f49Smrg 6332001f49Smrgstatic GLfloat Bias = -0.06; 6432001f49Smrg 6532001f49Smrgstatic GLboolean Anim = GL_TRUE; 6632001f49Smrg 6732001f49Smrgstatic GLboolean NeedNewShadowMap = GL_FALSE; 6832001f49Smrgstatic GLuint ShadowTexture, GrayTexture; 6932001f49Smrgstatic GLuint ShadowFBO; 7032001f49Smrg 7132001f49Smrgstatic GLfloat lightModelview[16]; 7232001f49Smrgstatic GLfloat lightProjection[16]; 7332001f49Smrg 7432001f49Smrgstatic GLuint vert_prog; 7532001f49Smrgstatic GLuint frag_progs[3]; 7632001f49Smrgstatic GLuint curr_frag = 0; 7732001f49Smrgstatic GLuint max_frag = 1; 7832001f49Smrg 7932001f49Smrg#define NUM_FRAG_MODES 3 8032001f49Smrgstatic const char *FragProgNames[] = { 8132001f49Smrg "fixed-function", 8232001f49Smrg "program without \"OPTION ARB_fragment_program_shadow\"", 8332001f49Smrg "program with \"OPTION ARB_fragment_program_shadow\"", 8432001f49Smrg}; 8532001f49Smrg 8632001f49Smrgstatic GLboolean HaveShadow = GL_FALSE; 8732001f49Smrgstatic GLboolean HaveFBO = GL_FALSE; 8832001f49Smrgstatic GLboolean UseFBO = GL_FALSE; 8932001f49Smrgstatic GLboolean HaveVP = GL_FALSE; 9032001f49Smrgstatic GLboolean HaveFP = GL_FALSE; 9132001f49Smrgstatic GLboolean HaveFP_Shadow = GL_FALSE; 9232001f49Smrgstatic GLboolean UseVP = GL_FALSE; 9332001f49Smrgstatic GLboolean HavePackedDepthStencil = GL_FALSE; 9432001f49Smrgstatic GLboolean UsePackedDepthStencil = GL_FALSE; 9532001f49Smrgstatic GLboolean HaveEXTshadowFuncs = GL_FALSE; 9632001f49Smrgstatic GLboolean HaveShadowAmbient = GL_FALSE; 9732001f49Smrg 9832001f49Smrgstatic GLint Operator = 0; 9932001f49Smrgstatic const GLenum OperatorFunc[8] = { 10032001f49Smrg GL_LEQUAL, GL_LESS, GL_GEQUAL, GL_GREATER, 10132001f49Smrg GL_EQUAL, GL_NOTEQUAL, GL_ALWAYS, GL_NEVER }; 10232001f49Smrgstatic const char *OperatorName[8] = { 10332001f49Smrg "GL_LEQUAL", "GL_LESS", "GL_GEQUAL", "GL_GREATER", 10432001f49Smrg "GL_EQUAL", "GL_NOTEQUAL", "GL_ALWAYS", "GL_NEVER" }; 10532001f49Smrg 10632001f49Smrg 10732001f49Smrgstatic GLuint DisplayMode; 10832001f49Smrg#define SHOW_SHADOWS 0 10932001f49Smrg#define SHOW_DEPTH_IMAGE 1 11032001f49Smrg#define SHOW_DEPTH_MAPPING 2 11132001f49Smrg#define SHOW_DISTANCE 3 11232001f49Smrg 11332001f49Smrg 11432001f49Smrg 11532001f49Smrg#define MAT4_MUL(dest_vec, src_mat, src_vec) \ 11632001f49Smrg "DP4 " dest_vec ".x, " src_mat "[0], " src_vec ";\n" \ 11732001f49Smrg "DP4 " dest_vec ".y, " src_mat "[1], " src_vec ";\n" \ 11832001f49Smrg "DP4 " dest_vec ".z, " src_mat "[2], " src_vec ";\n" \ 11932001f49Smrg "DP4 " dest_vec ".w, " src_mat "[3], " src_vec ";\n" 12032001f49Smrg 12132001f49Smrg#define MAT3_MUL(dest_vec, src_mat, src_vec) \ 12232001f49Smrg "DP3 " dest_vec ".x, " src_mat "[0], " src_vec ";\n" \ 12332001f49Smrg "DP3 " dest_vec ".y, " src_mat "[1], " src_vec ";\n" \ 12432001f49Smrg "DP3 " dest_vec ".z, " src_mat "[2], " src_vec ";\n" 12532001f49Smrg 12632001f49Smrg#define NORMALIZE(dest, src) \ 12732001f49Smrg "DP3 " dest ".w, " src ", " src ";\n" \ 12832001f49Smrg "RSQ " dest ".w, " dest ".w;\n" \ 12932001f49Smrg "MUL " dest ", " src ", " dest ".w;\n" 13032001f49Smrg 13132001f49Smrg/** 13232001f49Smrg * Vertex program for shadow mapping. 13332001f49Smrg */ 13432001f49Smrgstatic const char vert_code[] = 13532001f49Smrg "!!ARBvp1.0\n" 13632001f49Smrg "ATTRIB iPos = vertex.position;\n" 13732001f49Smrg "ATTRIB iNorm = vertex.normal;\n" 13832001f49Smrg 13932001f49Smrg "PARAM mvinv[4] = { state.matrix.modelview.invtrans };\n" 14032001f49Smrg "PARAM mvp[4] = { state.matrix.mvp };\n" 14132001f49Smrg "PARAM mv[4] = { state.matrix.modelview };\n" 14232001f49Smrg "PARAM texmat[4] = { state.matrix.texture[0] };\n" 14332001f49Smrg "PARAM lightPos = state.light[0].position;\n" 14432001f49Smrg "PARAM ambientCol = state.lightprod[0].ambient;\n" 14532001f49Smrg "PARAM diffuseCol = state.lightprod[0].diffuse;\n" 14632001f49Smrg 14732001f49Smrg "TEMP n, lightVec;\n" 14832001f49Smrg "ALIAS V = lightVec;\n" 14932001f49Smrg "ALIAS NdotL = n;\n" 15032001f49Smrg 15132001f49Smrg "OUTPUT oPos = result.position;\n" 15232001f49Smrg "OUTPUT oColor = result.color;\n" 15332001f49Smrg "OUTPUT oTex = result.texcoord[0];\n" 15432001f49Smrg 15532001f49Smrg /* Transform the vertex to clip coordinates. */ 15632001f49Smrg MAT4_MUL("oPos", "mvp", "iPos") 15732001f49Smrg 15832001f49Smrg /* Transform the vertex to eye coordinates. */ 15932001f49Smrg MAT4_MUL("V", "mv", "iPos") 16032001f49Smrg 16132001f49Smrg /* Transform the vertex to projected light coordinates. */ 16232001f49Smrg MAT4_MUL("oTex", "texmat", "iPos") 16332001f49Smrg 16432001f49Smrg /* Transform the normal to eye coordinates. */ 16532001f49Smrg MAT3_MUL("n", "mvinv", "iNorm") 16632001f49Smrg 16732001f49Smrg /* Calculate the vector from the vertex to the light in eye 16832001f49Smrg * coordinates. 16932001f49Smrg */ 17032001f49Smrg "SUB lightVec, lightPos, V;\n" 17132001f49Smrg NORMALIZE("lightVec", "lightVec") 17232001f49Smrg 17332001f49Smrg /* Compute diffuse lighting coefficient. 17432001f49Smrg */ 17532001f49Smrg "DP3 NdotL.x, n, lightVec;\n" 17632001f49Smrg "MAX NdotL.x, NdotL.x, {0.0};\n" 17732001f49Smrg "MIN NdotL.x, NdotL.x, {1.0};\n" 17832001f49Smrg 17932001f49Smrg /* Accumulate color contributions. 18032001f49Smrg */ 18132001f49Smrg "MOV oColor, diffuseCol;\n" 18232001f49Smrg "MAD oColor.xyz, NdotL.x, diffuseCol, ambientCol;\n" 18332001f49Smrg "END\n" 18432001f49Smrg ; 18532001f49Smrg 18632001f49Smrgstatic const char frag_code[] = 18732001f49Smrg "!!ARBfp1.0\n" 18832001f49Smrg 18932001f49Smrg "TEMP shadow, temp;\n" 19032001f49Smrg 19132001f49Smrg "TXP shadow, fragment.texcoord[0], texture[0], 2D;\n" 19232001f49Smrg "RCP temp.x, fragment.texcoord[0].w;\n" 19332001f49Smrg "MUL temp.x, temp.x, fragment.texcoord[0].z;\n" 19432001f49Smrg "SGE shadow, shadow.x, temp.x;\n" 19532001f49Smrg "MUL result.color.rgb, fragment.color, shadow.x;\n" 19632001f49Smrg "MOV result.color.a, fragment.color;\n" 19732001f49Smrg "END\n" 19832001f49Smrg ; 19932001f49Smrg 20032001f49Smrgstatic const char frag_shadow_code[] = 20132001f49Smrg "!!ARBfp1.0\n" 20232001f49Smrg "OPTION ARB_fragment_program_shadow;\n" 20332001f49Smrg 20432001f49Smrg "TEMP shadow;\n" 20532001f49Smrg 20632001f49Smrg "TXP shadow, fragment.texcoord[0], texture[0], SHADOW2D;\n" 20732001f49Smrg "MUL result.color.rgb, fragment.color, shadow.x;\n" 20832001f49Smrg "MOV result.color.a, fragment.color.a;\n" 20932001f49Smrg "END\n" 21032001f49Smrg ; 21132001f49Smrg 21232001f49Smrgstatic void 21332001f49SmrgDrawScene(void) 21432001f49Smrg{ 21532001f49Smrg GLfloat k = 6; 21632001f49Smrg 21732001f49Smrg /* sphere */ 21832001f49Smrg glPushMatrix(); 21932001f49Smrg glTranslatef(1.6, 2.2, 2.7); 22032001f49Smrg glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Green); 22132001f49Smrg glColor4fv(Green); 22232001f49Smrg glutSolidSphere(1.5, 15, 15); 22332001f49Smrg glPopMatrix(); 22432001f49Smrg /* dodecahedron */ 22532001f49Smrg glPushMatrix(); 22632001f49Smrg glTranslatef(-2.0, 1.2, 2.1); 22732001f49Smrg glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Red); 22832001f49Smrg glColor4fv(Red); 22932001f49Smrg glutSolidDodecahedron(); 23032001f49Smrg glPopMatrix(); 23132001f49Smrg /* icosahedron */ 23232001f49Smrg glPushMatrix(); 23332001f49Smrg glTranslatef(-0.6, 1.3, -0.5); 23432001f49Smrg glScalef(1.5, 1.5, 1.5); 23532001f49Smrg glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Yellow); 23632001f49Smrg glColor4fv(Red); 23732001f49Smrg glutSolidIcosahedron(); 23832001f49Smrg glPopMatrix(); 23932001f49Smrg /* a plane */ 24032001f49Smrg glPushMatrix(); 24132001f49Smrg glTranslatef(0, -1.1, 0); 24232001f49Smrg glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Blue); 24332001f49Smrg glColor4fv(Blue); 24432001f49Smrg glNormal3f(0, 1, 0); 24532001f49Smrg glBegin(GL_POLYGON); 24632001f49Smrg glVertex3f(-k, 0, -k); 24732001f49Smrg glVertex3f( k, 0, -k); 24832001f49Smrg glVertex3f( k, 0, k); 24932001f49Smrg glVertex3f(-k, 0, k); 25032001f49Smrg glEnd(); 25132001f49Smrg glPopMatrix(); 25232001f49Smrg} 25332001f49Smrg 25432001f49Smrg 25532001f49Smrg/** 25632001f49Smrg * Calculate modelview and project matrices for the light 25732001f49Smrg * 25832001f49Smrg * Stores the results in \c lightProjection (projection matrix) and 25932001f49Smrg * \c lightModelview (modelview matrix). 26032001f49Smrg */ 26132001f49Smrgstatic void 26232001f49SmrgMakeShadowMatrix(const GLfloat lightPos[4], const GLfloat spotDir[3], 26332001f49Smrg GLfloat spotAngle, GLfloat shadowNear, GLfloat shadowFar) 26432001f49Smrg{ 26532001f49Smrg /* compute frustum to enclose spot light cone */ 26632001f49Smrg const GLfloat d = shadowNear * tan(spotAngle); 26732001f49Smrg 26832001f49Smrg glMatrixMode(GL_PROJECTION); 26932001f49Smrg glPushMatrix(); 27032001f49Smrg glLoadIdentity(); 27132001f49Smrg glFrustum(-d, d, -d, d, shadowNear, shadowFar); 27232001f49Smrg glGetFloatv(GL_PROJECTION_MATRIX, lightProjection); 27332001f49Smrg glPopMatrix(); 27432001f49Smrg 27532001f49Smrg glMatrixMode(GL_MODELVIEW); 27632001f49Smrg glPushMatrix(); 27732001f49Smrg glLoadIdentity(); 27832001f49Smrg gluLookAt(lightPos[0], lightPos[1], lightPos[2], 27932001f49Smrg lightPos[0] + spotDir[0], 28032001f49Smrg lightPos[1] + spotDir[1], 28132001f49Smrg lightPos[2] + spotDir[2], 28232001f49Smrg 0.0, 1.0, 0.0); 28332001f49Smrg glGetFloatv(GL_MODELVIEW_MATRIX, lightModelview); 28432001f49Smrg glPopMatrix(); 28532001f49Smrg} 28632001f49Smrg 28732001f49Smrg 28832001f49Smrg/** 28932001f49Smrg * Load \c GL_TEXTURE matrix with light's MVP matrix. 29032001f49Smrg */ 29132001f49Smrgstatic void SetShadowTextureMatrix(void) 29232001f49Smrg{ 29332001f49Smrg static const GLfloat biasMatrix[16] = { 29432001f49Smrg 0.5, 0.0, 0.0, 0.0, 29532001f49Smrg 0.0, 0.5, 0.0, 0.0, 29632001f49Smrg 0.0, 0.0, 0.5, 0.0, 29732001f49Smrg 0.5, 0.5, 0.5, 1.0, 29832001f49Smrg }; 29932001f49Smrg 30032001f49Smrg glMatrixMode(GL_TEXTURE); 30132001f49Smrg glLoadMatrixf(biasMatrix); 30232001f49Smrg glTranslatef(0.0, 0.0, Bias); 30332001f49Smrg glMultMatrixf(lightProjection); 30432001f49Smrg glMultMatrixf(lightModelview); 30532001f49Smrg glMatrixMode(GL_MODELVIEW); 30632001f49Smrg} 30732001f49Smrg 30832001f49Smrg 30932001f49Smrgstatic void 31032001f49SmrgEnableIdentityTexgen(void) 31132001f49Smrg{ 31232001f49Smrg /* texgen so that texcoord = vertex coord */ 31332001f49Smrg static GLfloat sPlane[4] = { 1, 0, 0, 0 }; 31432001f49Smrg static GLfloat tPlane[4] = { 0, 1, 0, 0 }; 31532001f49Smrg static GLfloat rPlane[4] = { 0, 0, 1, 0 }; 31632001f49Smrg static GLfloat qPlane[4] = { 0, 0, 0, 1 }; 31732001f49Smrg 31832001f49Smrg glTexGenfv(GL_S, GL_EYE_PLANE, sPlane); 31932001f49Smrg glTexGenfv(GL_T, GL_EYE_PLANE, tPlane); 32032001f49Smrg glTexGenfv(GL_R, GL_EYE_PLANE, rPlane); 32132001f49Smrg glTexGenfv(GL_Q, GL_EYE_PLANE, qPlane); 32232001f49Smrg glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); 32332001f49Smrg glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); 32432001f49Smrg glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); 32532001f49Smrg glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); 32632001f49Smrg 32732001f49Smrg glEnable(GL_TEXTURE_GEN_S); 32832001f49Smrg glEnable(GL_TEXTURE_GEN_T); 32932001f49Smrg glEnable(GL_TEXTURE_GEN_R); 33032001f49Smrg glEnable(GL_TEXTURE_GEN_Q); 33132001f49Smrg} 33232001f49Smrg 33332001f49Smrg 33432001f49Smrg/* 33532001f49Smrg * Setup 1-D texgen so that the distance from the light source, between 33632001f49Smrg * the near and far planes maps to s=0 and s=1. When we draw the scene, 33732001f49Smrg * the grayness will indicate the fragment's distance from the light 33832001f49Smrg * source. 33932001f49Smrg */ 34032001f49Smrgstatic void 34132001f49SmrgEnableDistanceTexgen(const GLfloat lightPos[4], const GLfloat lightDir[3], 34232001f49Smrg GLfloat lightNear, GLfloat lightFar) 34332001f49Smrg{ 34432001f49Smrg GLfloat m, d; 34532001f49Smrg GLfloat sPlane[4]; 34632001f49Smrg GLfloat nearPoint[3]; 34732001f49Smrg 34832001f49Smrg m = sqrt(lightDir[0] * lightDir[0] + 34932001f49Smrg lightDir[1] * lightDir[1] + 35032001f49Smrg lightDir[2] * lightDir[2]); 35132001f49Smrg 35232001f49Smrg d = lightFar - lightNear; 35332001f49Smrg 35432001f49Smrg /* nearPoint = point on light direction vector which intersects the 35532001f49Smrg * near plane of the light frustum. 35632001f49Smrg */ 35732001f49Smrg nearPoint[0] = lightPos[0] + lightDir[0] / m * lightNear; 35832001f49Smrg nearPoint[1] = lightPos[1] + lightDir[1] / m * lightNear; 35932001f49Smrg nearPoint[2] = lightPos[2] + lightDir[2] / m * lightNear; 36032001f49Smrg 36132001f49Smrg sPlane[0] = lightDir[0] / d / m; 36232001f49Smrg sPlane[1] = lightDir[1] / d / m; 36332001f49Smrg sPlane[2] = lightDir[2] / d / m; 36432001f49Smrg sPlane[3] = -(sPlane[0] * nearPoint[0] 36532001f49Smrg + sPlane[1] * nearPoint[1] 36632001f49Smrg + sPlane[2] * nearPoint[2]); 36732001f49Smrg 36832001f49Smrg glTexGenfv(GL_S, GL_EYE_PLANE, sPlane); 36932001f49Smrg glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); 37032001f49Smrg glEnable(GL_TEXTURE_GEN_S); 37132001f49Smrg} 37232001f49Smrg 37332001f49Smrg 37432001f49Smrgstatic void 37532001f49SmrgDisableTexgen(void) 37632001f49Smrg{ 37732001f49Smrg glDisable(GL_TEXTURE_GEN_S); 37832001f49Smrg glDisable(GL_TEXTURE_GEN_T); 37932001f49Smrg glDisable(GL_TEXTURE_GEN_R); 38032001f49Smrg glDisable(GL_TEXTURE_GEN_Q); 38132001f49Smrg} 38232001f49Smrg 38332001f49Smrg 38432001f49Smrgstatic void 38532001f49SmrgComputeLightPos(GLfloat dist, GLfloat latitude, GLfloat longitude, 38632001f49Smrg GLfloat pos[4], GLfloat dir[3]) 38732001f49Smrg{ 38832001f49Smrg 38932001f49Smrg pos[0] = dist * sin(longitude * DEG_TO_RAD); 39032001f49Smrg pos[1] = dist * sin(latitude * DEG_TO_RAD); 39132001f49Smrg pos[2] = dist * cos(latitude * DEG_TO_RAD) * cos(longitude * DEG_TO_RAD); 39232001f49Smrg pos[3] = 1; 39332001f49Smrg dir[0] = -pos[0]; 39432001f49Smrg dir[1] = -pos[1]; 39532001f49Smrg dir[2] = -pos[2]; 39632001f49Smrg} 39732001f49Smrg 39832001f49Smrg 39932001f49Smrg/** 40032001f49Smrg * Render the shadow map / depth texture. 40132001f49Smrg * The result will be in the texture object named ShadowTexture. 40232001f49Smrg */ 40332001f49Smrgstatic void 40432001f49SmrgRenderShadowMap(void) 40532001f49Smrg{ 40632001f49Smrg GLenum depthFormat; /* GL_DEPTH_COMPONENT or GL_DEPTH_STENCIL_EXT */ 40732001f49Smrg GLenum depthType; /* GL_UNSIGNED_INT_24_8_EXT or GL_UNSIGNED_INT */ 40832001f49Smrg 40932001f49Smrg if (WindowWidth >= 1024 && WindowHeight >= 1024) { 41032001f49Smrg ShadowTexWidth = ShadowTexHeight = 1024; 41132001f49Smrg } 41232001f49Smrg else if (WindowWidth >= 512 && WindowHeight >= 512) { 41332001f49Smrg ShadowTexWidth = ShadowTexHeight = 512; 41432001f49Smrg } 41532001f49Smrg else if (WindowWidth >= 256 && WindowHeight >= 256) { 41632001f49Smrg ShadowTexWidth = ShadowTexHeight = 256; 41732001f49Smrg } 41832001f49Smrg else { 41932001f49Smrg ShadowTexWidth = ShadowTexHeight = 128; 42032001f49Smrg } 42132001f49Smrg printf("Rendering %d x %d depth texture\n", ShadowTexWidth, ShadowTexHeight); 42232001f49Smrg 42332001f49Smrg if (UsePackedDepthStencil) { 42432001f49Smrg depthFormat = GL_DEPTH_STENCIL_EXT; 42532001f49Smrg depthType = GL_UNSIGNED_INT_24_8_EXT; 42632001f49Smrg } 42732001f49Smrg else { 42832001f49Smrg depthFormat = GL_DEPTH_COMPONENT; 42932001f49Smrg depthType = GL_UNSIGNED_INT; 43032001f49Smrg } 43132001f49Smrg 43232001f49Smrg glMatrixMode(GL_PROJECTION); 43332001f49Smrg glLoadMatrixf(lightProjection); 43432001f49Smrg 43532001f49Smrg glMatrixMode(GL_MODELVIEW); 43632001f49Smrg glLoadMatrixf(lightModelview); 43732001f49Smrg 43832001f49Smrg if (UseFBO) { 43932001f49Smrg GLenum fbo_status; 44032001f49Smrg 44132001f49Smrg glTexImage2D(GL_TEXTURE_2D, 0, depthFormat, 44232001f49Smrg ShadowTexWidth, ShadowTexHeight, 0, 44332001f49Smrg depthFormat, depthType, NULL); 44432001f49Smrg 44532001f49Smrg /* Set the filter mode so that the texture is texture-complete. 44632001f49Smrg * Otherwise it will cause the framebuffer to fail the framebuffer 44732001f49Smrg * completeness test. 44832001f49Smrg */ 44932001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 45032001f49Smrg 45132001f49Smrg glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, ShadowFBO); 45232001f49Smrg glDrawBuffer(GL_NONE); 45332001f49Smrg glReadBuffer(GL_NONE); 45432001f49Smrg 45532001f49Smrg fbo_status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); 45632001f49Smrg if (fbo_status != GL_FRAMEBUFFER_COMPLETE_EXT) { 45732001f49Smrg fprintf(stderr, "FBO not complete! status = 0x%04x\n", fbo_status); 45832001f49Smrg assert(fbo_status == GL_FRAMEBUFFER_COMPLETE_EXT); 45932001f49Smrg } 46032001f49Smrg } 46132001f49Smrg 46232001f49Smrg assert(!glIsEnabled(GL_TEXTURE_1D)); 46332001f49Smrg assert(!glIsEnabled(GL_TEXTURE_2D)); 46432001f49Smrg 46532001f49Smrg glViewport(0, 0, ShadowTexWidth, ShadowTexHeight); 46632001f49Smrg glClear(GL_DEPTH_BUFFER_BIT); 46732001f49Smrg glEnable(GL_DEPTH_TEST); 46832001f49Smrg DrawScene(); 46932001f49Smrg 47032001f49Smrg if (UseFBO) { 47132001f49Smrg /* all done! */ 47232001f49Smrg glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); 47332001f49Smrg } 47432001f49Smrg else { 47532001f49Smrg /* 47632001f49Smrg * copy depth buffer into the texture map 47732001f49Smrg */ 47832001f49Smrg if (DisplayMode == SHOW_DEPTH_MAPPING) { 47932001f49Smrg /* load depth image as gray-scale luminance texture */ 48032001f49Smrg GLuint *depth = (GLuint *) 48132001f49Smrg malloc(ShadowTexWidth * ShadowTexHeight * sizeof(GLuint)); 48232001f49Smrg assert(depth); 48332001f49Smrg glReadPixels(0, 0, ShadowTexWidth, ShadowTexHeight, 48432001f49Smrg depthFormat, depthType, depth); 48532001f49Smrg glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 48632001f49Smrg ShadowTexWidth, ShadowTexHeight, 0, 48732001f49Smrg GL_LUMINANCE, GL_UNSIGNED_INT, depth); 48832001f49Smrg free(depth); 48932001f49Smrg } 49032001f49Smrg else { 49132001f49Smrg /* The normal shadow case - a real depth texture */ 49232001f49Smrg glCopyTexImage2D(GL_TEXTURE_2D, 0, depthFormat, 49332001f49Smrg 0, 0, ShadowTexWidth, ShadowTexHeight, 0); 49432001f49Smrg if (UsePackedDepthStencil) { 49532001f49Smrg /* debug check */ 49632001f49Smrg GLint intFormat; 49732001f49Smrg glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, 49832001f49Smrg GL_TEXTURE_INTERNAL_FORMAT, &intFormat); 49932001f49Smrg assert(intFormat == GL_DEPTH_STENCIL_EXT); 50032001f49Smrg } 50132001f49Smrg } 50232001f49Smrg } 50332001f49Smrg} 50432001f49Smrg 50532001f49Smrg 50632001f49Smrg/** 50732001f49Smrg * Show the shadow map as a grayscale image. 50832001f49Smrg */ 50932001f49Smrgstatic void 51032001f49SmrgShowShadowMap(void) 51132001f49Smrg{ 51232001f49Smrg glClear(GL_COLOR_BUFFER_BIT); 51332001f49Smrg 51432001f49Smrg glMatrixMode(GL_TEXTURE); 51532001f49Smrg glLoadIdentity(); 51632001f49Smrg 51732001f49Smrg glMatrixMode(GL_PROJECTION); 51832001f49Smrg glLoadIdentity(); 51932001f49Smrg glOrtho(0, WindowWidth, 0, WindowHeight, -1, 1); 52032001f49Smrg 52132001f49Smrg glMatrixMode(GL_MODELVIEW); 52232001f49Smrg glLoadIdentity(); 52332001f49Smrg 52432001f49Smrg glDisable(GL_DEPTH_TEST); 52532001f49Smrg glDisable(GL_LIGHTING); 52632001f49Smrg 52732001f49Smrg glEnable(GL_TEXTURE_2D); 52832001f49Smrg 52932001f49Smrg DisableTexgen(); 53032001f49Smrg 53132001f49Smrg /* interpret texture's depth values as luminance values */ 53232001f49Smrg if (HaveShadow) { 53332001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE); 53432001f49Smrg } 53532001f49Smrg 53632001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE); 53732001f49Smrg glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 53832001f49Smrg 53932001f49Smrg glBegin(GL_POLYGON); 54032001f49Smrg glTexCoord2f(0, 0); glVertex2f(0, 0); 54132001f49Smrg glTexCoord2f(1, 0); glVertex2f(ShadowTexWidth, 0); 54232001f49Smrg glTexCoord2f(1, 1); glVertex2f(ShadowTexWidth, ShadowTexHeight); 54332001f49Smrg glTexCoord2f(0, 1); glVertex2f(0, ShadowTexHeight); 54432001f49Smrg glEnd(); 54532001f49Smrg 54632001f49Smrg glDisable(GL_TEXTURE_2D); 54732001f49Smrg glEnable(GL_DEPTH_TEST); 54832001f49Smrg glEnable(GL_LIGHTING); 54932001f49Smrg} 55032001f49Smrg 55132001f49Smrg 55232001f49Smrg/** 55332001f49Smrg * Redraw window image 55432001f49Smrg */ 55532001f49Smrgstatic void 55632001f49SmrgDisplay(void) 55732001f49Smrg{ 55832001f49Smrg GLenum error; 55932001f49Smrg 56032001f49Smrg ComputeLightPos(LightDist, LightLatitude, LightLongitude, 56132001f49Smrg LightPos, SpotDir); 56232001f49Smrg 56332001f49Smrg if (NeedNewShadowMap) { 56432001f49Smrg MakeShadowMatrix(LightPos, SpotDir, SpotAngle, ShadowNear, ShadowFar); 56532001f49Smrg RenderShadowMap(); 56632001f49Smrg NeedNewShadowMap = GL_FALSE; 56732001f49Smrg } 56832001f49Smrg 56932001f49Smrg glViewport(0, 0, WindowWidth, WindowHeight); 57032001f49Smrg if (DisplayMode == SHOW_DEPTH_IMAGE) { 57132001f49Smrg ShowShadowMap(); 57232001f49Smrg } 57332001f49Smrg else { 57432001f49Smrg /* prepare to draw scene from camera's view */ 57532001f49Smrg const GLfloat ar = (GLfloat) WindowWidth / (GLfloat) WindowHeight; 57632001f49Smrg 57732001f49Smrg glMatrixMode(GL_PROJECTION); 57832001f49Smrg glLoadIdentity(); 57932001f49Smrg glFrustum(-ar, ar, -1.0, 1.0, 4.0, 50.0); 58032001f49Smrg 58132001f49Smrg glMatrixMode(GL_MODELVIEW); 58232001f49Smrg glLoadIdentity(); 58332001f49Smrg glTranslatef(0.0, 0.0, -22.0); 58432001f49Smrg glRotatef(Xrot, 1, 0, 0); 58532001f49Smrg glRotatef(Yrot, 0, 1, 0); 58632001f49Smrg glRotatef(Zrot, 0, 0, 1); 58732001f49Smrg 58832001f49Smrg glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 58932001f49Smrg 59032001f49Smrg glLightfv(GL_LIGHT0, GL_POSITION, LightPos); 59132001f49Smrg 59232001f49Smrg if (LinearFilter) { 59332001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 59432001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 59532001f49Smrg } 59632001f49Smrg else { 59732001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 59832001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 59932001f49Smrg } 60032001f49Smrg 60132001f49Smrg if (DisplayMode == SHOW_DEPTH_MAPPING) { 60232001f49Smrg if (HaveShadow) { 60332001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE); 60432001f49Smrg } 60532001f49Smrg glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 60632001f49Smrg glEnable(GL_TEXTURE_2D); 60732001f49Smrg 60832001f49Smrg SetShadowTextureMatrix(); 60932001f49Smrg EnableIdentityTexgen(); 61032001f49Smrg } 61132001f49Smrg else if (DisplayMode == SHOW_DISTANCE) { 61232001f49Smrg glMatrixMode(GL_TEXTURE); 61332001f49Smrg glLoadIdentity(); 61432001f49Smrg glMatrixMode(GL_MODELVIEW); 61532001f49Smrg EnableDistanceTexgen(LightPos, SpotDir, ShadowNear+Bias, ShadowFar); 61632001f49Smrg glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 61732001f49Smrg glEnable(GL_TEXTURE_1D); 61832001f49Smrg assert(!glIsEnabled(GL_TEXTURE_2D)); 61932001f49Smrg } 62032001f49Smrg else { 62132001f49Smrg assert(DisplayMode == SHOW_SHADOWS); 62232001f49Smrg if (HaveShadow) { 62332001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, 62432001f49Smrg GL_COMPARE_R_TO_TEXTURE_ARB); 62532001f49Smrg } 62632001f49Smrg 62732001f49Smrg if (curr_frag > 0) { 62832001f49Smrg glEnable(GL_FRAGMENT_PROGRAM_ARB); 62932001f49Smrg } 63032001f49Smrg else { 63132001f49Smrg glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 63232001f49Smrg } 63332001f49Smrg glEnable(GL_TEXTURE_2D); 63432001f49Smrg 63532001f49Smrg SetShadowTextureMatrix(); 63632001f49Smrg 63732001f49Smrg if (UseVP) { 63832001f49Smrg glEnable(GL_VERTEX_PROGRAM_ARB); 63932001f49Smrg } 64032001f49Smrg else { 64132001f49Smrg glEnable(GL_LIGHTING); 64232001f49Smrg EnableIdentityTexgen(); 64332001f49Smrg } 64432001f49Smrg } 64532001f49Smrg 64632001f49Smrg DrawScene(); 64732001f49Smrg 64832001f49Smrg if (UseVP) { 64932001f49Smrg glDisable(GL_VERTEX_PROGRAM_ARB); 65032001f49Smrg } 65132001f49Smrg else { 65232001f49Smrg DisableTexgen(); 65332001f49Smrg glDisable(GL_LIGHTING); 65432001f49Smrg } 65532001f49Smrg 65632001f49Smrg if (curr_frag > 0) { 65732001f49Smrg glDisable(GL_FRAGMENT_PROGRAM_ARB); 65832001f49Smrg } 65932001f49Smrg 66032001f49Smrg glDisable(GL_TEXTURE_1D); 66132001f49Smrg glDisable(GL_TEXTURE_2D); 66232001f49Smrg } 66332001f49Smrg 66432001f49Smrg glutSwapBuffers(); 66532001f49Smrg 66632001f49Smrg error = glGetError(); 66732001f49Smrg if (error) { 66832001f49Smrg printf("GL Error: %s\n", (char *) gluErrorString(error)); 66932001f49Smrg } 67032001f49Smrg} 67132001f49Smrg 67232001f49Smrg 67332001f49Smrgstatic void 67432001f49SmrgReshape(int width, int height) 67532001f49Smrg{ 67632001f49Smrg WindowWidth = width; 67732001f49Smrg WindowHeight = height; 67832001f49Smrg NeedNewShadowMap = GL_TRUE; 67932001f49Smrg} 68032001f49Smrg 68132001f49Smrg 68232001f49Smrgstatic void 68332001f49SmrgIdle(void) 68432001f49Smrg{ 68532001f49Smrg static double t0 = -1.; 68632001f49Smrg double dt, t = glutGet(GLUT_ELAPSED_TIME) / 1000.0; 68732001f49Smrg if (t0 < 0.0) 68832001f49Smrg t0 = t; 68932001f49Smrg dt = t - t0; 69032001f49Smrg t0 = t; 69132001f49Smrg Yrot += 75.0 * dt; 69232001f49Smrg /*LightLongitude -= 5.0;*/ 69332001f49Smrg glutPostRedisplay(); 69432001f49Smrg} 69532001f49Smrg 69632001f49Smrg 69732001f49Smrgstatic void 69832001f49SmrgKey(unsigned char key, int x, int y) 69932001f49Smrg{ 70032001f49Smrg const GLfloat step = 3.0; 70132001f49Smrg (void) x; 70232001f49Smrg (void) y; 70332001f49Smrg switch (key) { 70432001f49Smrg case 'a': 70532001f49Smrg Anim = !Anim; 70632001f49Smrg if (Anim) 70732001f49Smrg glutIdleFunc(Idle); 70832001f49Smrg else 70932001f49Smrg glutIdleFunc(NULL); 71032001f49Smrg break; 71132001f49Smrg case 'b': 71232001f49Smrg Bias -= 0.01; 71332001f49Smrg printf("Bias %g\n", Bias); 71432001f49Smrg break; 71532001f49Smrg case 'B': 71632001f49Smrg Bias += 0.01; 71732001f49Smrg printf("Bias %g\n", Bias); 71832001f49Smrg break; 71932001f49Smrg case 'd': 72032001f49Smrg DisplayMode = SHOW_DISTANCE; 72132001f49Smrg break; 72232001f49Smrg case 'f': 72332001f49Smrg LinearFilter = !LinearFilter; 72432001f49Smrg printf("%s filtering\n", LinearFilter ? "Bilinear" : "Nearest"); 72532001f49Smrg break; 72632001f49Smrg case 'i': 72732001f49Smrg DisplayMode = SHOW_DEPTH_IMAGE; 72832001f49Smrg break; 72932001f49Smrg case 'm': 73032001f49Smrg DisplayMode = SHOW_DEPTH_MAPPING; 73132001f49Smrg break; 73232001f49Smrg case 'M': 73332001f49Smrg curr_frag = (1 + curr_frag) % max_frag; 73432001f49Smrg if (!HaveShadow && (curr_frag == 0)) { 73532001f49Smrg curr_frag = 1; 73632001f49Smrg } 73732001f49Smrg 73832001f49Smrg printf("Using fragment %s\n", FragProgNames[curr_frag]); 73932001f49Smrg 74032001f49Smrg if (HaveFP) { 74132001f49Smrg glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, frag_progs[curr_frag]); 74232001f49Smrg } 74332001f49Smrg break; 74432001f49Smrg case 'n': 74532001f49Smrg case 's': 74632001f49Smrg case ' ': 74732001f49Smrg DisplayMode = SHOW_SHADOWS; 74832001f49Smrg break; 74932001f49Smrg case 'o': 75032001f49Smrg if (HaveEXTshadowFuncs) { 75132001f49Smrg Operator++; 75232001f49Smrg if (Operator >= 8) 75332001f49Smrg Operator = 0; 75432001f49Smrg printf("Operator: %s\n", OperatorName[Operator]); 75532001f49Smrg if (HaveShadow) { 75632001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, 75732001f49Smrg OperatorFunc[Operator]); 75832001f49Smrg } 75932001f49Smrg } 76032001f49Smrg break; 76132001f49Smrg case 'p': 76232001f49Smrg UsePackedDepthStencil = !UsePackedDepthStencil; 76332001f49Smrg if (UsePackedDepthStencil && !HavePackedDepthStencil) { 76432001f49Smrg printf("Sorry, GL_EXT_packed_depth_stencil not supported\n"); 76532001f49Smrg UsePackedDepthStencil = GL_FALSE; 76632001f49Smrg } 76732001f49Smrg else { 76832001f49Smrg printf("Use GL_DEPTH_STENCIL_EXT: %d\n", UsePackedDepthStencil); 76932001f49Smrg /* Don't really need to regenerate shadow map texture, but do so 77032001f49Smrg * to exercise more code more often. 77132001f49Smrg */ 77232001f49Smrg NeedNewShadowMap = GL_TRUE; 77332001f49Smrg } 77432001f49Smrg break; 77532001f49Smrg case 'v': 77632001f49Smrg UseVP = !UseVP && HaveVP; 77732001f49Smrg printf("Using vertex %s mode.\n", 77832001f49Smrg UseVP ? "program" : "fixed-function"); 77932001f49Smrg break; 78032001f49Smrg case 'z': 78132001f49Smrg Zrot -= step; 78232001f49Smrg break; 78332001f49Smrg case 'Z': 78432001f49Smrg Zrot += step; 78532001f49Smrg break; 78632001f49Smrg case 27: 78732001f49Smrg exit(0); 78832001f49Smrg break; 78932001f49Smrg } 79032001f49Smrg fflush(stdout); 79132001f49Smrg glutPostRedisplay(); 79232001f49Smrg} 79332001f49Smrg 79432001f49Smrg 79532001f49Smrgstatic void 79632001f49SmrgSpecialKey(int key, int x, int y) 79732001f49Smrg{ 79832001f49Smrg const GLfloat step = 3.0; 79932001f49Smrg const int mod = glutGetModifiers(); 80032001f49Smrg (void) x; 80132001f49Smrg (void) y; 80232001f49Smrg switch (key) { 80332001f49Smrg case GLUT_KEY_UP: 80432001f49Smrg if (mod) 80532001f49Smrg LightLatitude += step; 80632001f49Smrg else 80732001f49Smrg Xrot += step; 80832001f49Smrg break; 80932001f49Smrg case GLUT_KEY_DOWN: 81032001f49Smrg if (mod) 81132001f49Smrg LightLatitude -= step; 81232001f49Smrg else 81332001f49Smrg Xrot -= step; 81432001f49Smrg break; 81532001f49Smrg case GLUT_KEY_LEFT: 81632001f49Smrg if (mod) 81732001f49Smrg LightLongitude += step; 81832001f49Smrg else 81932001f49Smrg Yrot += step; 82032001f49Smrg break; 82132001f49Smrg case GLUT_KEY_RIGHT: 82232001f49Smrg if (mod) 82332001f49Smrg LightLongitude -= step; 82432001f49Smrg else 82532001f49Smrg Yrot -= step; 82632001f49Smrg break; 82732001f49Smrg } 82832001f49Smrg if (mod) 82932001f49Smrg NeedNewShadowMap = GL_TRUE; 83032001f49Smrg 83132001f49Smrg glutPostRedisplay(); 83232001f49Smrg} 83332001f49Smrg 83432001f49Smrg 83532001f49Smrg/* A helper for finding errors in program strings */ 83632001f49Smrgstatic int FindLine( const char *program, int position ) 83732001f49Smrg{ 83832001f49Smrg int i, line = 1; 83932001f49Smrg for (i = 0; i < position; i++) { 84032001f49Smrg if (program[i] == '\n') 84132001f49Smrg line++; 84232001f49Smrg } 84332001f49Smrg return line; 84432001f49Smrg} 84532001f49Smrg 84632001f49Smrg 84732001f49Smrgstatic GLuint 84832001f49Smrgcompile_program(GLenum target, const char *code) 84932001f49Smrg{ 85032001f49Smrg GLuint p; 85132001f49Smrg GLint errorPos; 85232001f49Smrg 85332001f49Smrg 85432001f49Smrg glGenProgramsARB(1, & p); 85532001f49Smrg 85632001f49Smrg glBindProgramARB(target, p); 85732001f49Smrg glProgramStringARB(target, GL_PROGRAM_FORMAT_ASCII_ARB, 85832001f49Smrg strlen(code), code); 85932001f49Smrg glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errorPos); 86032001f49Smrg if (glGetError() != GL_NO_ERROR || errorPos != -1) { 86132001f49Smrg int l = FindLine(code, errorPos); 86232001f49Smrg printf("Fragment Program Error (pos=%d line=%d): %s\n", errorPos, l, 86332001f49Smrg (char *) glGetString(GL_PROGRAM_ERROR_STRING_ARB)); 86432001f49Smrg exit(0); 86532001f49Smrg } 86632001f49Smrg 86732001f49Smrg glBindProgramARB(target, 0); 86832001f49Smrg return p; 86932001f49Smrg} 87032001f49Smrg 87132001f49Smrgstatic void 87232001f49SmrgInit(void) 87332001f49Smrg{ 87432001f49Smrg static const GLfloat borderColor[4] = {1.0, 0.0, 0.0, 0.0}; 87532001f49Smrg 87632001f49Smrg if (!glutExtensionSupported("GL_ARB_depth_texture")) { 87732001f49Smrg printf("Sorry, this demo requires the GL_ARB_depth_texture extension\n"); 87832001f49Smrg exit(1); 87932001f49Smrg } 88032001f49Smrg 88132001f49Smrg HaveShadow = glutExtensionSupported("GL_ARB_shadow"); 88232001f49Smrg HaveVP = glutExtensionSupported("GL_ARB_vertex_program"); 88332001f49Smrg HaveFP = glutExtensionSupported("GL_ARB_fragment_program"); 88432001f49Smrg HaveFP_Shadow = glutExtensionSupported("GL_ARB_fragment_program_shadow"); 88532001f49Smrg 88632001f49Smrg if (!HaveShadow && !HaveFP) { 88732001f49Smrg printf("Sorry, this demo requires either the GL_ARB_shadow extension " 88832001f49Smrg "or the GL_ARB_fragment_program extension\n"); 88932001f49Smrg exit(1); 89032001f49Smrg } 89132001f49Smrg 89232001f49Smrg printf("Using GL_ARB_depth_texture\n"); 89332001f49Smrg if (HaveShadow) { 89432001f49Smrg printf("and GL_ARB_shadow\n"); 89532001f49Smrg } 89632001f49Smrg 89732001f49Smrg if (HaveFP) { 89832001f49Smrg printf("and GL_ARB_fragment_program\n"); 89932001f49Smrg } 90032001f49Smrg 90132001f49Smrg HaveShadowAmbient = glutExtensionSupported("GL_ARB_shadow_ambient"); 90232001f49Smrg if (HaveShadowAmbient) { 90332001f49Smrg printf("and GL_ARB_shadow_ambient\n"); 90432001f49Smrg } 90532001f49Smrg 90632001f49Smrg HaveEXTshadowFuncs = glutExtensionSupported("GL_EXT_shadow_funcs"); 90732001f49Smrg 90832001f49Smrg HavePackedDepthStencil = glutExtensionSupported("GL_EXT_packed_depth_stencil"); 90932001f49Smrg UsePackedDepthStencil = HavePackedDepthStencil; 91032001f49Smrg 91132001f49Smrg#if defined(GL_EXT_framebuffer_object) 91232001f49Smrg HaveFBO = glutExtensionSupported("GL_EXT_framebuffer_object"); 91332001f49Smrg UseFBO = HaveFBO; 91432001f49Smrg if (UseFBO) { 91532001f49Smrg printf("Using GL_EXT_framebuffer_object\n"); 91632001f49Smrg } 91732001f49Smrg#endif 91832001f49Smrg 91932001f49Smrg /* 92032001f49Smrg * Set up the 2D shadow map texture 92132001f49Smrg */ 92232001f49Smrg glGenTextures(1, &ShadowTexture); 92332001f49Smrg glBindTexture(GL_TEXTURE_2D, ShadowTexture); 92432001f49Smrg glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); 92532001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); 92632001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); 92732001f49Smrg 92832001f49Smrg if (HaveShadow) { 92932001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, 93032001f49Smrg GL_COMPARE_R_TO_TEXTURE_ARB); 93132001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL); 93232001f49Smrg } 93332001f49Smrg 93432001f49Smrg if (HaveShadowAmbient) { 93532001f49Smrg glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FAIL_VALUE_ARB, 0.3); 93632001f49Smrg } 93732001f49Smrg 93832001f49Smrg#if defined(GL_EXT_framebuffer_object) 93932001f49Smrg if (UseFBO) { 94032001f49Smrg glGenFramebuffersEXT(1, &ShadowFBO); 94132001f49Smrg glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, ShadowFBO); 94232001f49Smrg glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, 94332001f49Smrg GL_COLOR_ATTACHMENT0_EXT, 94432001f49Smrg GL_RENDERBUFFER_EXT, 0); 94532001f49Smrg glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, 94632001f49Smrg GL_TEXTURE_2D, ShadowTexture, 0); 94732001f49Smrg 94832001f49Smrg glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); 94932001f49Smrg } 95032001f49Smrg#endif 95132001f49Smrg 95232001f49Smrg /* 95332001f49Smrg * Setup 1-D grayscale texture image for SHOW_DISTANCE mode 95432001f49Smrg */ 95532001f49Smrg glGenTextures(1, &GrayTexture); 95632001f49Smrg glBindTexture(GL_TEXTURE_1D, GrayTexture); 95732001f49Smrg glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP); 95832001f49Smrg glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 95932001f49Smrg glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 96032001f49Smrg { 96132001f49Smrg GLuint i; 96232001f49Smrg GLubyte image[256]; 96332001f49Smrg for (i = 0; i < 256; i++) 96432001f49Smrg image[i] = i; 96532001f49Smrg glTexImage1D(GL_TEXTURE_1D, 0, GL_LUMINANCE, 96632001f49Smrg 256, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, image); 96732001f49Smrg } 96832001f49Smrg 96932001f49Smrg if (HaveVP) { 97032001f49Smrg vert_prog = compile_program(GL_VERTEX_PROGRAM_ARB, vert_code); 97132001f49Smrg glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vert_prog); 97232001f49Smrg } 97332001f49Smrg 97432001f49Smrg max_frag = 1; 97532001f49Smrg frag_progs[0] = 0; 97632001f49Smrg 97732001f49Smrg if (HaveFP) { 97832001f49Smrg frag_progs[1] = compile_program(GL_FRAGMENT_PROGRAM_ARB, frag_code); 97932001f49Smrg max_frag = 2; 98032001f49Smrg } 98132001f49Smrg 98232001f49Smrg if (HaveFP && HaveFP_Shadow) { 98332001f49Smrg frag_progs[2] = compile_program(GL_FRAGMENT_PROGRAM_ARB, 98432001f49Smrg frag_shadow_code); 98532001f49Smrg max_frag = 3; 98632001f49Smrg } 98732001f49Smrg 98832001f49Smrg if (!HaveShadow) { 98932001f49Smrg curr_frag = 1; 99032001f49Smrg glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, frag_progs[curr_frag]); 99132001f49Smrg } 99232001f49Smrg 99332001f49Smrg glEnable(GL_DEPTH_TEST); 99432001f49Smrg glEnable(GL_LIGHTING); 99532001f49Smrg glEnable(GL_LIGHT0); 99632001f49Smrg} 99732001f49Smrg 99832001f49Smrg 99932001f49Smrgstatic void 100032001f49SmrgPrintHelp(void) 100132001f49Smrg{ 100232001f49Smrg printf("Keys:\n"); 100332001f49Smrg printf(" a = toggle animation\n"); 100432001f49Smrg printf(" i = show depth texture image\n"); 100532001f49Smrg printf(" m = show depth texture mapping\n"); 100632001f49Smrg printf(" d = show fragment distance from light source\n"); 100732001f49Smrg printf(" n = show normal, shadowed image\n"); 100832001f49Smrg printf(" f = toggle nearest/bilinear texture filtering\n"); 100932001f49Smrg printf(" b/B = decrease/increase shadow map Z bias\n"); 101032001f49Smrg printf(" p = toggle use of packed depth/stencil\n"); 101132001f49Smrg printf(" M = cycle through fragment program modes\n"); 101232001f49Smrg printf(" v = toggle vertex program modes\n"); 101332001f49Smrg printf(" cursor keys = rotate scene\n"); 101432001f49Smrg printf(" <shift> + cursor keys = rotate light source\n"); 101532001f49Smrg if (HaveEXTshadowFuncs) 101632001f49Smrg printf(" o = cycle through comparison modes\n"); 101732001f49Smrg fflush(stdout); 101832001f49Smrg} 101932001f49Smrg 102032001f49Smrg 102132001f49Smrgint 102232001f49Smrgmain(int argc, char *argv[]) 102332001f49Smrg{ 102432001f49Smrg glutInitWindowSize(WindowWidth, WindowHeight); 102532001f49Smrg glutInit(&argc, argv); 102632001f49Smrg glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_STENCIL); 102732001f49Smrg glutCreateWindow(argv[0]); 102832001f49Smrg glewInit(); 102932001f49Smrg glutReshapeFunc(Reshape); 103032001f49Smrg glutKeyboardFunc(Key); 103132001f49Smrg glutSpecialFunc(SpecialKey); 103232001f49Smrg glutDisplayFunc(Display); 103332001f49Smrg if (Anim) 103432001f49Smrg glutIdleFunc(Idle); 103532001f49Smrg Init(); 103632001f49Smrg PrintHelp(); 103732001f49Smrg glutMainLoop(); 103832001f49Smrg return 0; 103932001f49Smrg} 1040