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

Related posts about lighting

Related posts about deferred-rendering