Hi,
I'm trying to us the Shadow mapping code from the OpenGL Orange Book listed below and I'm having troubles setting up everything to get it to work. I haven't done shadow mapping before, but I've included the setup code that I have for OpenGL and the actual display code. I've also noticed that I've been having an issue with depth buffer precision. If I just draw the shadow map on a texture, all of the objects seem to have the same depth value (despite this the current code does project some of the shape). Is there anyone that may be able to help me?
Thanks.
Vertex Shader
Code:
varying vec4 ShadowCoord;
const float As = 1.0 / 1.5;
const float Ds = 1.0 / 3.0;
void main()
{
vec4 ecPosition = gl_ModelViewMatrix * gl_Vertex;
vec3 ecPosition3 = (vec3(ecPosition)) / ecPosition.w;
vec3 VP = vec3(gl_LightSource[0].position) - ecPosition3;
VP = normalize(VP);
vec3 normal = normalize(gl_NormalMatrix * gl_Normal);
float diffuse = max(0.0, dot(normal, VP));
float scale = min(1.0, As + diffuse * Ds);
vec4 texCoord = gl_TextureMatrix[0] * gl_Vertex;
ShadowCoord = texCoord / texCoord.w;
gl_FrontColor = vec4(scale * gl_Color.rgb, gl_Color.a);
gl_Position = ftransform();
}
Fragment Shader
Code:
uniform sampler2DShadow ShadowMap;
uniform float Epsilon;
varying vec4 ShadowCoord;
float lookup(float x, float y)
{
float depth = shadow2DProj(ShadowMap, ShadowCoord + vec4(x, y, 0.0, 0.0) * Epsilon).x;
return depth != 1.0 ? 0.75 : 1.0;
}
void main()
{
float shadeFactor = lookup(0.0, 0.0);
gl_FragColor = vec4(shadeFactor * gl_Color.rgb, gl_Color.a);
}
OpenGL Initialization Code (not including shader code since I know that's set up properly).
Code:
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClearDepth(1.0f);
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, 1.0f, 1.0f, 100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// Set up the lighting
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
// Set up the texture
glGenTextures(1, &shadowMapTexture);
glBindTexture(GL_TEXTURE_2D, shadowMapTexture);
glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, shadowMapSize, shadowMapSize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
if ( myShader.installProgram() )
{
shaderProgram = myShader.getProgram();
texLoc = glGetUniformLocation(shaderProgram, "ShadowMap");
glUniform1f(texLoc, 0);
GLint temp = glGetUniformLocation(shaderProgram, "Epsilon");
glUniform1f(temp, 0.005);
// Since it has survived through our checks, it must've loaded properly.
return true;
}
Display Code
Code:
static float rotation = 0.0;
double lightProjectionMatrix[16], lightModelViewMatrix[16], sceneModelViewMatrix[16];
// Draw the first pass
glUseProgram(0);
glViewport(0, 0, shadowMapSize, shadowMapSize); // Bound it to the size of the texture map.
//Draw back faces into the shadow map
glCullFace(GL_FRONT);
//Disable color writes, and use flat shading for speed
glShadeModel(GL_FLAT);
glColorMask(0, 0, 0, 0); // Stop writing to the color buffer
glColorMask(1, 1, 1, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Set up the scene from the light's position
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(90.0, 1.0, 5.0, 20.0);
// Copy the light projection matrix
glGetDoublev(GL_PROJECTION_MATRIX, lightProjectionMatrix);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(lightPos[0], lightPos[1], lightPos[2], 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
// Copy the light model view matrix
glGetDoublev(GL_MODELVIEW_MATRIX, lightModelViewMatrix);
// Draw the scene
drawScene();
// Create a texture from it by copying it from the buffer.
glBindTexture(GL_TEXTURE_2D, shadowMapTexture);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, shadowMapSize, shadowMapSize); // Data automatically comes from depth buffer
// Draw the second pass
glUseProgram(shaderProgram);
//restore states
glCullFace(GL_BACK);
glShadeModel(GL_SMOOTH);
glColorMask(1, 1, 1, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Set up the actual view
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, 1.0f, 1.0f, 100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(20.0 * cos(rotation * degToRad), 15.0, 20.0 * sin(rotation * degToRad), 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
// Copy the current modelview matrix.
glGetDoublev(GL_MODELVIEW_MATRIX, sceneModelViewMatrix);
// Activate texture0
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, shadowMapTexture);
// Set up the texture matrix
glMatrixMode (GL_TEXTURE);
glLoadIdentity();
glTranslatef(0.5, 0.5, 0.5);
glScalef(0.5, 0.5, 0.5);
glMultMatrixd (lightProjectionMatrix);
glMultMatrixd (lightModelViewMatrix);
// Draw a pixel where the light is
glMatrixMode(GL_MODELVIEW);
glPointSize(4.0f);
glBegin(GL_POINTS);
glColor3f(1.0, 1.0, 0.0);
glVertex3fv(lightPos);
glEnd();
drawScene();
rotation++;
rotation = (rotation > 360.0) ? rotation / 360.0 : rotation;
glutSwapBuffers();