PDA

View Full Version : Basic shadowmapping problem



mobeen
01-28-2011, 04:44 AM
Hi all,
I have read the fabien tutorial on basic shadow mapping here http://www.fabiensanglard.net/shadowmapping/index.php but my shadow mapping is wrong. Check the attached image.
http://www3.ntu.edu.sg/home2007/mova0002/test/problem.png
I am calc. the lightMatrix using glm as follows.


lightOffsetMatrix=glm::translate(glm::mat4(1.0f), glm::vec3(0.5,0.5,0.5));
lightOffsetMatrix=glm::scale(lightOffsetMatrix, glm::vec3(0.5,0.5,0.5));
lightMV = glmLookAt(glm::vec3(light_position[0], light_position[1], light_position[2]),glm::vec3(0.0f), glm::vec3(0.0,1.0,0.0));
lightMatrix = (lightOffsetMatrix* (P*lightMV));

I define the glmLookAt function like this


glm::mat4 glmLookAt(glm::vec3 eye, glm::vec3 tgt, glm::vec3 up) {
glm::vec3 F = tgt - eye;
F = glm::normalize(F);
glm::vec3 newUp = glm::normalize(up);
glm::vec3 s = glm::cross(F,newUp);
up = glm::cross(s,F);
glm::mat4 matrix=glm::mat4(1.0f);
matrix[0]=glm::vec4(s.x, up.x,-F.x,0);
matrix[1]=glm::vec4(s.y, up.y,-F.y,0);
matrix[2]=glm::vec4(s.z, up.z,-F.z,0);
return glm::translate(matrix, -eye);
}

My vertex shader is this,


#version 330
in vec2 vUV;
in vec3 vVertex;
in vec3 vNormal;

smooth out vec2 vTexCoord;
smooth out vec4 vShadowCoord;
smooth out vec4 color;

uniform mat3 N;
uniform mat4 MV;
uniform mat4 MVP;
uniform vec4 lightPos;
uniform vec4 mat_ambient;
uniform vec4 mat_diffuse;
uniform vec4 mat_specular;
uniform float mat_shininess;

uniform vec4 light_ambient;
uniform vec4 light_diffuse;
uniform vec4 light_specular;

uniform mat4 lightMatrix;
void main()
{
vTexCoord = vUV;
vec3 Nr = normalize(N*vNormal); //transform the normal vector by the normal matrix (inverse transpose of the modelview matrix)
vec4 esPos = MV*vec4(vVertex,1);
vec3 ecPosition3 = (vec3 (esPos.xyz)) / esPos.w;
vec3 V = vec3 (0.0, 0.0, 1.0);

// Compute vector from surface to light position
vec3 L = lightPos.xyz - ecPosition3;

// Normalize the vector from surface to light position
L = normalize(L);
vec3 H = normalize( V + L);

vec4 A = mat_ambient*light_ambient;
float diffuse = max(dot(Nr,L),0.0);
float pf=0;
if (diffuse == 0.0)
{
pf = 0.0;
}
else
{
pf = max( pow(dot(Nr,H), mat_shininess), 0.);

}
vec4 S = light_specular*mat_specular* pf;
vec4 D = diffuse*mat_diffuse*light_diffuse;

color = A + D + S;

vShadowCoord = (lightMatrix*vec4(vVertex,1)) ;
gl_Position = MVP*vec4(vVertex,1);
}
and the fragment shader is this,


#version 330
smooth in vec2 vTexCoord;
smooth in vec4 color;
smooth in vec4 vShadowCoord;
out vec4 vFragColor;
uniform sampler2D textureMap;
uniform bool has_texture;
uniform sampler2DShadow shadowMap;
void main(void)
{
if(has_texture)
vFragColor = texture(textureMap, vTexCoord)*color;
else
vFragColor = color;

float shadow = texture (shadowMap, vShadowCoord.xyz);
vFragColor *= shadow;
}

Am i missing anything obvious.

mobeen
01-28-2011, 05:36 AM
Just a quick note. There are two prblms here

1)I think my matrix for the ship is not set properly in the first pass since the plane should not be placed at the same position as in eye space. I am correcting it though. but still the shadow on the floor is wrong.

2) I am trying to render both objects in the light space however I only see the ground plane fine but the ship is never displayed. Since the ground plane is placed at origin its matrix is identity and so i set the light modelview matrix directly for it and it works fine. However for ship, it has an object tranform to position it given as follows,

glm::mat4 obj_matrix= glm::translate(glm::mat4(1), glm::vec3(tx,10,tz));
and so to get the lightMV for this object i multiply the light modelview matrix by the object's matrix,


glm::mat4 LMV = lightMV*obj_matrix;

I keep the same projection matrix for both light and camera.

Am i doing this wrongly?

mobeen
01-28-2011, 06:16 AM
Ok I think i messed my rendering code during this process and so my spaceship was not rendered now its perfectly fine. But my shadow is still in the same though a small warped ground plane in the middle.

mobeen
01-28-2011, 09:35 PM
I think the depth texture is fine now. Check the attached image however i still get the same output the shadow seems to stick to the middle and i see the clamping artifacts going all the way to the edge.
http://www3.ntu.edu.sg/home2007/mova0002/test/problem2.png

mobeen
01-28-2011, 10:31 PM
OK I modulate the object color with the shadow coordinates and this is what i get. Is this what i should get?
http://www3.ntu.edu.sg/home2007/mova0002/test/problem3.png

mobeen
01-28-2011, 10:48 PM
OK I need to ask one thing. When we multiply the lightMatrix to the vertex to obtain the shadow coordinates (that are used to lookup the shadowmap), which space should vertices be in?

Currently I am directly multiplying the object space positions and I feel its wrong since the lightMatrix does a scale and translate by (0.5,0.5,0.5) which brings the depth texture lookup coordinates btw 0-1 range and this is only possible if I use the clip space position of the vertex. Am i correct?

Dark Photon
01-29-2011, 05:50 PM
OK I need to ask one thing. When we multiply the lightMatrix to the vertex to obtain the shadow coordinates (that are used to lookup the shadowmap), which space should vertices be in?
Well, given what you provided above, you can answer that. You said:

I am calc. the lightMatrix using glm as follows.


lightOffsetMatrix=glm::translate(glm::mat4(1.0f), glm::vec3(0.5,0.5,0.5));
lightOffsetMatrix=glm::scale(lightOffsetMatrix,
glm::vec3(0.5,0.5,0.5));
lightMV = glmLookAt(glm::vec3(light_position[0],
light_position[1],
light_position[2]),
glm::vec3(0.0f),
glm::vec3(0.0,1.0,0.0));
lightMatrix = (lightOffsetMatrix* (P*lightMV));

In order of application, you have:
lightMV - Takes you from the space light_position is in to "Light EYE SPACE" P - Presumably takes you from "Light EYE SPACE" to "Light's CLIP SPACE" (in other words, this is the light's PROJECTION transform) lightOffsetMatrix - Takes you from "Light's CLIP SPACE" (-1..1) to "Light's TEXTURE SPACE" (0..1)So the whole thing takes you from the space "light_position" is in to "Light's TEXTURE SPACE". You know what space "light_position" is in.

Simple tutorials (like Fabien's, IIRC) often make this starting space "WORLD SPACE", but that's problematic once your worlds get large because "WORLD SPACE" coords may have magnitudes too big for 32-bit float precision with any reasonable accuracy. A more general solution is to augment your shadow transform to take you from Camera's EYE SPACE through WORLD SPACE, Light's EYE SPACE and Light's CLIP SPACE to Light's TEXTURE SPACE, as denoted by the diagram here:

http://www.paulsprojects.net/tutorials/smt/smt.html

http://www.paulsprojects.net/tutorials/smt/spaces.jpg

Same thing, except that you prepend the Camera's inverse VIEWING transform to get you from Camera's EYE SPACE to WORLD space.

Then your shader never needs to muck with WORLD SPACE coords, bypassing the 32-bit float precision problems that would otherwise occur.