I recently added "Shadow Mapping" in my XNA games to include shadows. I followed the nice and famous tutorial from "Riemers" :
http://www.riemers.net/eng/Tutorials/XNA/Csharp/Series3/Shadow_map.php .
This code work nice and I can see my source of light and shadow. But the problem is that my light source does not match the field of view that I created. I want the light covers the entire map of my game. I don't know why , but the light only affect 2-3 cubes of my map.
ScreenShot: (the emission of light illuminates only 2-3 blocks and not the full map)
Here is my code i create the fieldOfView for LightviewProjection Matrix:
Vector3 lightDir = new Vector3(10, 52, 10);
lightPos = new Vector3(10, 52, 10);
Matrix lightsView = Matrix.CreateLookAt(lightPos, new Vector3(105, 50, 105), new Vector3(0, 1, 0));
Matrix lightsProjection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver2, 1f, 20f, 1000f);
lightsViewProjectionMatrix = lightsView * lightsProjection;
As you can see , my nearPlane and FarPlane are set to 20f and 100f . So i don't know why the light stop after 2 cubes. it's should be bigger
Here is set the value to my custom effect HLSL in the shader file
/* SHADOW VALUE */
effectWorld.Parameters["LightDirection"].SetValue(lightDir);
effectWorld.Parameters["xLightsWorldViewProjection"].SetValue(Matrix.Identity * .lightsViewProjectionMatrix);
effectWorld.Parameters["xWorldViewProjection"].SetValue(Matrix.Identity * arcadia.camera.View * arcadia.camera.Projection);
effectWorld.Parameters["xLightPower"].SetValue(1f);
effectWorld.Parameters["xAmbient"].SetValue(0.3f);
Here is my custom HLSL shader effect file "*.fx"
// This sample uses a simple Lambert lighting model.
float3 LightDirection = normalize(float3(-1, -1, -1));
float3 DiffuseLight = 1.25;
float3 AmbientLight = 0.25;
uniform const float3 DiffuseColor = 1;
uniform const float Alpha = 1;
uniform const float3 EmissiveColor = 0;
uniform const float3 SpecularColor = 1;
uniform const float SpecularPower = 16;
uniform const float3 EyePosition;
// FOG attribut
uniform const float FogEnabled ;
uniform const float FogStart ;
uniform const float FogEnd ;
uniform const float3 FogColor ;
float3 cameraPos : CAMERAPOS;
texture Texture;
sampler Sampler = sampler_state
{
Texture = (Texture);
magfilter = LINEAR;
minfilter = LINEAR;
mipfilter = LINEAR;
AddressU = mirror;
AddressV = mirror;
};
texture xShadowMap;
sampler ShadowMapSampler = sampler_state
{
Texture = <xShadowMap>;
magfilter = LINEAR;
minfilter = LINEAR;
mipfilter = LINEAR;
AddressU = clamp;
AddressV = clamp;
};
/* *************** */
/* SHADOW MAP CODE */
/* *************** */
struct SMapVertexToPixel
{
float4 Position : POSITION;
float4 Position2D : TEXCOORD0;
};
struct SMapPixelToFrame
{
float4 Color : COLOR0;
};
struct SSceneVertexToPixel
{
float4 Position : POSITION;
float4 Pos2DAsSeenByLight : TEXCOORD0;
float2 TexCoords : TEXCOORD1;
float3 Normal : TEXCOORD2;
float4 Position3D : TEXCOORD3;
};
struct SScenePixelToFrame
{
float4 Color : COLOR0;
};
float DotProduct(float3 lightPos, float3 pos3D, float3 normal)
{
float3 lightDir = normalize(pos3D - lightPos);
return dot(-lightDir, normal);
}
SSceneVertexToPixel ShadowedSceneVertexShader(float4 inPos : POSITION, float2 inTexCoords : TEXCOORD0, float3 inNormal : NORMAL)
{
SSceneVertexToPixel Output = (SSceneVertexToPixel)0;
Output.Position = mul(inPos, xWorldViewProjection);
Output.Pos2DAsSeenByLight = mul(inPos, xLightsWorldViewProjection);
Output.Normal = normalize(mul(inNormal, (float3x3)World));
Output.Position3D = mul(inPos, World);
Output.TexCoords = inTexCoords;
return Output;
}
SScenePixelToFrame ShadowedScenePixelShader(SSceneVertexToPixel PSIn)
{
SScenePixelToFrame Output = (SScenePixelToFrame)0;
float2 ProjectedTexCoords;
ProjectedTexCoords[0] = PSIn.Pos2DAsSeenByLight.x / PSIn.Pos2DAsSeenByLight.w / 2.0f + 0.5f;
ProjectedTexCoords[1] = -PSIn.Pos2DAsSeenByLight.y / PSIn.Pos2DAsSeenByLight.w / 2.0f + 0.5f;
float diffuseLightingFactor = 0;
if ((saturate(ProjectedTexCoords).x == ProjectedTexCoords.x) && (saturate(ProjectedTexCoords).y == ProjectedTexCoords.y))
{
float depthStoredInShadowMap = tex2D(ShadowMapSampler, ProjectedTexCoords).r;
float realDistance = PSIn.Pos2DAsSeenByLight.z / PSIn.Pos2DAsSeenByLight.w;
if ((realDistance - 1.0f / 100.0f) <= depthStoredInShadowMap)
{
diffuseLightingFactor = DotProduct(xLightPos, PSIn.Position3D, PSIn.Normal);
diffuseLightingFactor = saturate(diffuseLightingFactor);
diffuseLightingFactor *= xLightPower;
}
}
float4 baseColor = tex2D(Sampler, PSIn.TexCoords);
Output.Color = baseColor*(diffuseLightingFactor + xAmbient);
return Output;
}
SMapVertexToPixel ShadowMapVertexShader(float4 inPos : POSITION)
{
SMapVertexToPixel Output = (SMapVertexToPixel)0;
Output.Position = mul(inPos, xLightsWorldViewProjection);
Output.Position2D = Output.Position;
return Output;
}
SMapPixelToFrame ShadowMapPixelShader(SMapVertexToPixel PSIn)
{
SMapPixelToFrame Output = (SMapPixelToFrame)0;
Output.Color = PSIn.Position2D.z / PSIn.Position2D.w;
return Output;
}
/* ******************* */
/* END SHADOW MAP CODE */
/* ******************* */
/ For rendering without instancing.
technique ShadowMap
{
pass Pass0
{
VertexShader = compile vs_2_0 ShadowMapVertexShader();
PixelShader = compile ps_2_0 ShadowMapPixelShader();
}
}
technique ShadowedScene
{
/*
pass Pass0
{
VertexShader = compile vs_2_0 VSBasicTx();
PixelShader = compile ps_2_0 PSBasicTx();
}
*/
pass Pass1
{
VertexShader = compile vs_2_0 ShadowedSceneVertexShader();
PixelShader = compile ps_2_0 ShadowedScenePixelShader();
}
}
technique SimpleFog
{
pass Pass0
{
VertexShader = compile vs_2_0 VSBasicTx();
PixelShader = compile ps_2_0 PSBasicTx();
}
}
I edited my fx file , for show you only information and functions about the shadow ;-)