Shadow mapping with deffered shading for directional lights - shadow map projection problem
Posted
by
Harry
on Game Development
See other posts from Game Development
or by Harry
Published on 2013-09-22T20:24:08Z
Indexed on
2013/11/04
22:17 UTC
Read the original article
Hit count: 451
I'm trying to implement shadow mapping to my engine. I started with directional lights because they seemed to be the easiest one, but I was wrong :) I have implemented deferred shading and I retrieve position from depth. I think that there is the biggest problem but code looks ok for me.
Now more about problem:
Shadow map projected onto meshes looks bad scaled and translated and also some informations from shadow map texture aren't visible. You can see it on this screen: http://img5.imageshack.us/img5/2254/93dn.png
Yelow frustum is light frustum and I have mixed shadow map preview and actual scene. As you can see shadows are in wrong place and shadow of cone and sphere aren't visible.
Could you look at my codes and tell me where I have a mistake?
// create shadow map
if(!_shd)glGenTextures(1, &_shd);
glBindTexture(GL_TEXTURE_2D, _shd);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 1024, 1024, 0, GL_DEPTH_COMPONENT, GL_FLOAT,NULL); // shadow map size
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, _shd, 0);
glDrawBuffer(GL_NONE);
// setting camera
Vector dire=Vector(0,0,1);
ACamera.setLookAt(dire,Vector(0));
ACamera.setPerspectiveView(60.0f,1,0.1f,10.0f); // currently needed for proper frustum corners calculation
Vector min(ACamera._point[0]),max(ACamera._point[0]);
for(int i=0;i<8;i++){
max=Max(max,ACamera._point[i]);
min=Min(min,ACamera._point[i]);
}
ACamera.setOrthogonalView(min.x,max.x,min.y,max.y,-max.z,-min.z);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _s_buffer); // framebuffer for shadow map
// rendering to depth buffer
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _g_buffer);
Shaders["DirLight"].set(true);
Matrix4 bias;
bias.x.set(0.5,0.0,0.0,0.0);
bias.y.set(0.0,0.5,0.0,0.0);
bias.z.set(0.0,0.0,0.5,0.0);
bias.w.set(0.5,0.5,0.5,1.0);
Shaders["DirLight"].set("textureMatrix",ACamera.matrix*Projection3D*bias); // order of multiplications are 100% correct, everything gives mi the same result as using glm
glActiveTexture(GL_TEXTURE5);
glBindTexture(GL_TEXTURE_2D,_shd);
lightDir(dir); // light calculations
Vertex Shader makes nothing related to shadow calculatons
Pixel shader function which calculates if pixel is in shadow or not:
float readShadowMap(vec3 eyeDir)
{
// retrieve depth of pixel
float z = texture2D(depth, gl_FragCoord.xy/screen).z;
vec3 pos = vec3(gl_FragCoord.xy/screen, z);
// transform by the projection and view inverse
vec4 worldSpace = inverse(View)*inverse(ProjectionMatrix)*vec4(pos*2-1,1);
worldSpace /= worldSpace.w;
vec4 coord=textureMatrix*worldSpace;
float vis=1.0f;
if(texture2D(shadow, coord.xy).z < coord.z-0.001)vis=0.2f;
return vis;
}
I also have question about shadows specifically for directional light. Currently I always look at 0,0,0 position and in further implementation I have to move light frustum along to camera frustum. I've found how to do this here: http://www.gamedev.net/topic/505893-orthographic-projection-for-shadow-mapping/ but it doesn't give me what I want. Maybe because of problems mentioned above, but I want know your opinion.
EDIT:
vec4 worldSpace is position read from depht of the scene (not shadow map). Maybe I wasn't precise so I'll try quick explain what is what: View is camera view matrix, ProjectionMatrix is camera projection,. First I try to get world space position from depth map and then multiply it by textureMatrix which is light view *light projection*bias. Rest of code is the same as in many tutorials. I can't use vertex shader to make something like gl_Position=textureMatrix*gl_Vertex and get it interpolated in fragment shader because of deffered rendering use so I want get it from depht buffer.
EDIT2:
I also tried make it as in Coding Labs tutorial about Shadow Mapping with Deferred Rendering but unfortunately this either works wrong.
© Game Development or respective owner