Original Post
Hi I've written a shadow mapping effect file based on the example from render monkey:
it seems okay execept for two problems: 1. all lights point at the origin i.e. 0,0,0. 2. the shadow cast on the ground seems to be the wrong way round. can anyone see why this is happening and can anyone suggest how i can add a target or direction to my lights? thanks.
//--------------------------------------------------------------//
// Shadow Mapping
//--------------------------------------------------------------//
texture2D ShadowMap_Tex : RenderColorTarget
<
float2 ViewportRatio= float2(1.0f,1.0f);
string Format="D3DFMT_A8R8G8B8";
>;
sampler2D ShadowMap = sampler_state
{
Texture = (ShadowMap_Tex);
ADDRESSU = CLAMP;
ADDRESSV = CLAMP;
MAGFILTER = LINEAR;
MINFILTER = LINEAR;
MIPFILTER = LINEAR;
};
texture2D SpotLight_Tex
<
string ResourceName = "Spotlight.jpg";
>;
sampler2D SpotLight = sampler_state
{
Texture = (SpotLight_Tex);
ADDRESSU = CLAMP;
ADDRESSV = CLAMP;
MAGFILTER = LINEAR;
MINFILTER = LINEAR;
MIPFILTER = LINEAR;
};
float4x4 proj_matrix : Projection;
float4x4 view_proj_matrix : WorldViewProjection;
float4 lightPos;
float4 view_position : CameraPosition;
float backProjectionCut = 2000.00000f;
float3 up = float3(0,1,0);
float distanceScale
<
string UIName = "distanceScale";
string UIWidget = "Numeric";
float UIMin = 0.00;
float UIMax = 1.00;
> = 0.00148f;
float shadowBias
<
string UIName = "shadowBias";
string UIWidget = "Numeric";
float UIMin = 0.00;
float UIMax = 0.01;
> = 0.004f;
struct VS_OUTPUT
{
float4 Pos: POSITION;
float3 lightVec: TEXCOORD0;
};
VS_OUTPUT depth_vs_main(float4 inPos: POSITION)
{
VS_OUTPUT Out;
// Create view vectors for the light, looking at (0,0,0)
float3 dirZ = -normalize(lightPos);
float3 dirX = cross(up, dirZ);
float3 dirY = cross(dirZ, dirX);
// Transform into light's view space.
float4 pos;
inPos.xyz -= lightPos;
pos.x = dot(dirX, inPos);
pos.y = dot(dirY, inPos);
pos.z = dot(dirZ, inPos);
pos.w = 1;
// Project the object into the light's view
Out.Pos = mul(pos,proj_matrix);
Out.lightVec = distanceScale * inPos;
return Out;
}
float4 depth_ps_main(float3 lightVec: TEXCOORD0) : COLOR
{
// Output radial distance
return length(lightVec);
}
//--------------------------------------------------------------//
// Object
//--------------------------------------------------------------//
struct object_VS_OUTPUT
{
float4 Pos: POSITION;
float3 normal: TEXCOORD0;
float3 lightVec : TEXCOORD1;
float3 viewVec: TEXCOORD2;
float4 shadowCrd: TEXCOORD3;
};
object_VS_OUTPUT object_vs_main(
float4 inPos: POSITION,
float3 inNormal: NORMAL)
{
object_VS_OUTPUT Out;
// Project the object's position
Out.Pos = mul(inPos,view_proj_matrix);
// World-space lighting
Out.normal = inNormal;
Out.lightVec = distanceScale * (lightPos - inPos.xyz);
Out.viewVec = view_position - inPos.xyz;
// Create view vectors for the light, looking at (0,0,0)
float3 dirZ = -normalize(lightPos);
float3 dirX = cross(up, dirZ);
float3 dirY = cross(dirZ, dirX);
// Transform into light's view space.
float4 pos;
inPos.xyz -= lightPos;
pos.x = dot(dirX, inPos);
pos.y = dot(dirY, inPos);
pos.z = dot(dirZ, inPos);
pos.w = 1;
// Project it into light space to determine she shadow
// map position
float4 sPos = mul(pos,proj_matrix);
// Use projective texturing to map the position of each fragment
// to its corresponding texel in the shadow map.
sPos.z += 10;
Out.shadowCrd.x = 0.5 * (sPos.z + sPos.x);
Out.shadowCrd.y = 0.5 * (sPos.z - sPos.y);
Out.shadowCrd.z = 0;
Out.shadowCrd.w = sPos.z;
return Out;
}
float4 object_ps_main(
float3 inNormal: TEXCOORD0,
float3 lightVec: TEXCOORD1,
float3 viewVec: TEXCOORD2,
float4 shadowCrd: TEXCOORD3) : COLOR
{
// Radial distance and normalize light vector
float depth = length(lightVec);
lightVec /= depth;
// The depth of the fragment closest to the light
float4 shadowMap;
float offset = (2.0/1024.0)*shadowCrd.w;
shadowMap.x = tex2Dproj(ShadowMap, shadowCrd+float4(offset,0,0,0));
shadowMap.y = tex2Dproj(ShadowMap, shadowCrd+float4(-offset,0,0,0));
shadowMap.z = tex2Dproj(ShadowMap, shadowCrd+float4(0,offset,0,0));
shadowMap.w = tex2Dproj(ShadowMap, shadowCrd+float4(0,-offset,0,0));
// A spot image of the spotlight
float spotLight = tex2Dproj(SpotLight, shadowCrd);
// If the depth is larger than the stored depth, this fragment
// is not the closest to the light, that is we are in shadow.
// Otherwise, we're lit. Add a bias to avoid precision issues.
float shadow;
shadow = (float)(depth < shadowMap.x + shadowBias)/4.0;
shadow += (float)(depth < shadowMap.y + shadowBias)/4.0;
shadow += (float)(depth < shadowMap.z + shadowBias)/4.0;
shadow += (float)(depth < shadowMap.w + shadowBias)/4.0;
// Modulate with spotlight image
float shadowval = spotLight*shadow;
// Shadow any light contribution except ambient
float4 colour = shadowval;
colour.w = 1.0f;
return colour;
}
//--------------------------------------------------------------//
// Technique Section for Shadow Mapping
//--------------------------------------------------------------//
technique DepthPass
{
pass Depth
{
VertexShader = compile vs_1_1 depth_vs_main();
PixelShader = compile ps_2_0 depth_ps_main();
}
}
technique ObjectPass
{
pass Object
{
VertexShader = compile vs_1_1 object_vs_main();
PixelShader = compile ps_2_0 object_ps_main();
}
}