I've been following the tutorials listed below:
http://www.riemers.net/eng/Tutorials/XNA/Csharp/Series3/Shadow_map.php
http://xbox.create.msdn.com/en-US/education/catalog/sample/shadow_mapping_1
And I made my shadow map creator effect:
float4x4 WorldViewProjection;
float4x4 LightingWorld;
float4x4 LightingViewProjection;
struct VertexToPixel {
float4 Position : POSITION;
float Depth : TEXCOORD0;
};
VertexToPixel ShadowMapVertexShader(float4 position : POSITION) {
VertexToPixel output = (VertexToPixel)0;
output.Position = mul(position, mul(LightingWorld, LightingViewProjection));
output.Depth = output.Position.z / output.Position.w;
return output;
}
float4 ShadowMapPixelShader(VertexToPixel input) : COLOR0 {
float4 color = input.Depth;
color.a = 1;
return color;
}
I use the following flashlight (which has a cone angle: coneAngleHalfRad * 2) View and Projection matrices for the shadow map (and for checking the depths later):
lightProjection = Matrix.CreatePerspectiveFieldOfView(
coneAngleHalfRad * 2,
1,
1, //0.25f,
range);
//Helper.Message(this, "draw shadow maps: " + needsShadows);
//Helper.Message(this, "rotation up: " + rotation.Up);
lightView = Matrix.CreateLookAt(position, position + (direction * range), rotation.Up);
lightViewProjection = lightView * lightProjection;
DepthMapMakerEffect.Parameters["LightingWorld"].SetValue(Matrix.Identity);
DepthMapMakerEffect.Parameters["LightingViewProjection"].SetValue(lightViewProjection);
DepthMapMakerEffect.Techniques[0].Passes[0].Apply();
device.SetRenderTarget(RenderDirectional);
device.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Black, 1.0f, 0);
drawAction(this, DepthMapMakerEffect);
device.SetRenderTarget(null);
ShadowMapDirectional = (Texture2D)RenderDirectional;
I set my shadow map to the effect:
TextureManager.DynamicTexturingEffect.Parameters["Flashlight" + numFlashlightsPP + "Map"].SetValue(((Flashlight)lights[lightIndex]).ShadowMapDirectional);
And when I am drawing the light with additive blend state, I use the following code to get the depths from the shadow map and from the camera (is it from the camera? I didn't understand yet):
shared float DepthBias = 0.001f;
// [...]
shared Texture Flashlight0Map;
shared sampler Flashlight0MapSampler = sampler_state {
texture = <Flashlight0Map>;
magfilter = LINEAR;
minfilter = LINEAR;
mipfilter = LINEAR;
AddressU = clamp;
AddressV = clamp;
};
// [...]
// Find the position of this pixel in light space.
float4 lightingPosition = mul(worldPosition, flashlight.LightingViewProjection);
// Find the position in the shadow map for this pixel.
float2 shadowTexCoord = 0.5 * lightingPosition.xy /
lightingPosition.w + float2(0.5, 0.5);
shadowTexCoord.y = 1.0f - shadowTexCoord.y;
// Get the current depth stored in the shadow map.
float shadowDepth = tex2D(Flashlight0MapSampler, shadowTexCoord).r;
// Calculate the current pixel depth.
// The bias is used to prevent folating point errors that occur when
// the pixel of the occluder is being drawn.
float ourDepth = (lightingPosition.z / lightingPosition.w) - DepthBias;
// [...]
float intensity = 0;
if (ourDepth <= shadowDepth) {
if (atten > 0) {
intensity = saturate((flashlight.Range - dist) / flashlight.Range) * (dot(vertexNormal, perVertexNormal) * fog) * atten;
}
}
But what happens is that the result is ALWAYS "ourDepth > shadowDepth", which makes the entire light always hidden so it's always shadowed no matter if there's an object in front of it or not.
What could I possible be doing wrong? I think I used wrong values in the flashlight's View and Projection. But I can't find the error. What might be the problem?
Any suggestion may help!
EDIT: I'm not using the same aspect ratio of the screen and of the camera for the shadow map. Do I need to?