Hello,
I am attempting to implement shadow mapping, but am failing pretty horribly.
For some reason, the shadows are in a completely wrong place, and not even oriented correctly:
http://imgur.com/ROEgP
What could cause this?
Shadow mapping problem
Looks like you're using the wrong view matrix when rendering the shadow, or when projecting the shadow-map.
How do you calculate your matrices?
How do you calculate your matrices?
Quote:Original post by Hodgman
Looks like you're using the wrong view matrix when rendering the shadow, or when projecting the shadow-map.
How do you calculate your matrices?
I calculate the view matrix in c++ and pass it to the shader:
D3DXMatrixLookAtLH(&worldToLight,&(light.pos),&(light.dir),&(Vec3(0,1,0)));
that is your lookat, but you need to create your projection matrix too and combine them. Usually, you create an orthographic projection. Good luck..
http://www.d3dcoder.net/d3d10.aspx
For some good information and code on how to do shadow mapping, download part III, unzip it, and check the folder chapter 13. It is about shadow mapping.
http://www.d3dcoder.net/d3d10.aspx
For some good information and code on how to do shadow mapping, download part III, unzip it, and check the folder chapter 13. It is about shadow mapping.
Quote:Original post by smasherprog
that is your lookat, but you need to create your projection matrix too and combine them. Usually, you create an orthographic projection.
Hmm, yes, I have that, too:
D3DXMatrixPerspectiveFovLH(&lightProjection, D3DXToRadian(90), (FLOAT)resX / (FLOAT)resY, NEAR_PLANE, FAR_PLANE);
Your view matrix is wrong. The LookAt parameter isn't a direction vector, it's a point at which the camera looks. So you want to do this:
D3DXVECTOR3 lookAt = light.pos + light.dir;D3DXMatrixLookAtLH(&worldToLight,&(light.pos),&lookAt,&(Vec3(0,1,0)));
Quote:Original post by MJP
Your view matrix is wrong. The LookAt parameter isn't a direction vector, it's a point at which the camera looks. So you want to do this:D3DXVECTOR3 lookAt = light.pos + light.dir;D3DXMatrixLookAtLH(&worldToLight,&(light.pos),&lookAt,&(Vec3(0,1,0)));
Wow, good call. But it doesn't change the incorrect shadows...
Is there anything wrong with my shader code?
Here is the code for rendering the shadow map (which looks correct):
/* posView is the pixel in light space, because the view matrix is temporarily using the light as a "camera"*/return float4(IN.posView.z,IN.posView.z,IN.posView.z,1.0);
Here is where I use the shadow map texture:
float Shadow = 1.0; if(shadowMapExists) { /*convert pixel position in light space to NDC, then to the range [0,1]*/ float4 posTex = mul(IN.posLight,lightProjection); posTex += float4(1,1,1,0); posTex *= 0.5; /*use converted pixel position to index into the texture*/ /*sampled values should be between the near plane and far plane; [1.0,10000]*/ float D = tex2D(shadowSampler,float2(posTex.x,posTex.y)).z; /* if the pixel value is smaller than the sampled value, it means there is something in front of the pixel, in light space; the pixel is in shadow*/ if( IN.posLight.z < D ) Shadow -= 1.0; }
If you're using a perspective projection you need to perform homogeneous divide-by-w before you can use X and Y as a texture coordinate. This brings the coordinates into the [-1, 1] range which you can then convert to [0, 1] range (which you're already doing).
After that, you also need to flip the y coordinate around. After divide-by-w, y is -1 at the bottom and 1 at the top. This is the opposite of texture coordinates, where 0 is the top and -1 is the bottom. Try this:
After that, you also need to flip the y coordinate around. After divide-by-w, y is -1 at the bottom and 1 at the top. This is the opposite of texture coordinates, where 0 is the top and -1 is the bottom. Try this:
float4 posTex = mul(IN.posLight,lightProjection);posTex /= posTex.w;posTex += float4(1,1,1,0);posTex *= 0.5;posTex.y = 1.0f - posTex.y;
Quote:Original post by MJP
If you're using a perspective projection you need to perform homogeneous divide-by-w before you can use X and Y as a texture coordinate. This brings the coordinates into the [-1, 1] range which you can then convert to [0, 1] range (which you're already doing).
After that, you also need to flip the y coordinate around. After divide-by-w, y is -1 at the bottom and 1 at the top. This is the opposite of texture coordinates, where 0 is the top and -1 is the bottom. Try this:float4 posTex = mul(IN.posLight,lightProjection);posTex /= posTex.w;posTex += float4(1,1,1,0);posTex *= 0.5;posTex.y = 1.0f - posTex.y;
Cool, I did not know that.
The shadows actually look decent now, but there are a lot of problems with them. The biggest problem are the z-values.
Currently, I use 1/pixelInLightSpace.z for both the shadow map and testing against the shadow map. This is because the biggest differences are now in the [0,1] range. However, it is still non-linear and causes problems.
Some other problems are:
-Small bands of light between an object and its shadow
-Occasional shadow-light stripes
-Weird behavior when the light is far away from the object
Does anybody know any solutions to these problems?
[Edited by - xytor on October 16, 2010 10:57:42 PM]
1.The small bands of light you are seeing is the inaccuracy in float. This is totally normal.
2.This is also a problem with inaccuracy with float, try adding more bias (might make small bands of light bigger).
http://developer.nvidia.com/object/hwshadowmap_paper.html shows you how to solve this.
3.The further the light is away the higher your shadow Map resolution need to be for you to get better results.If I understand you correctly.
Hope this helps.
2.This is also a problem with inaccuracy with float, try adding more bias (might make small bands of light bigger).
http://developer.nvidia.com/object/hwshadowmap_paper.html shows you how to solve this.
3.The further the light is away the higher your shadow Map resolution need to be for you to get better results.If I understand you correctly.
Hope this helps.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement