This topic is 2828 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

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?

##### Share on other sites
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?

##### Share on other sites
Quote:
 Original post by HodgmanLooks 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)));

##### Share on other sites
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.

##### Share on other sites
Quote:
 Original post by smasherprogthat 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);

##### Share on other sites
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)));

##### Share on other sites
Quote:
 Original post by MJPYour 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;				}

##### Share on other sites
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;

##### Share on other sites
Quote:
 Original post by MJPIf 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
-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]

##### Share on other sites
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.

1. 1
2. 2
Rutin
21
3. 3
JoeJ
18
4. 4
5. 5

• 14
• 39
• 23
• 13
• 13
• ### Forum Statistics

• Total Topics
631717
• Total Posts
3001878
×