Click to enlarge if you cannot read the text.
Here is the shader to generate the shadow map
float4x4 dsObjectWorld : WORLD;
float4x4 dsLightView : VIEW;
float4x4 dsLightProjection : PROJECTION;
void vsDSShadowMap(float4 iPos : POSITION0,
out float4 oPos : POSITION0,
out float oDepth : TEXCOORD0)
{
float4 vWorldPos = mul(iPos, dsObjectWorld);
float4 vLightViewPos = mul(vWorldPos, dsLightView);
oPos = mul(vLightViewPos, dsLightProjection);
oDepth = oPos.z / oPos.w;
}
void psDSShadowMap(float iDepth : TEXCOORD0,
out float4 oDepth : COLOR0)
{
oDepth = float4(iDepth, 0.0f, 0.0f, 1.0f);
}
technique ShadowMap
{
pass ShadowMapRender
{
VertexShader = compile vs_2_0 vsDSShadowMap();
PixelShader = compile ps_2_0 psDSShadowMap();
}
}
And the calculation shader
float4x4 cameraViewProjectionInverse;
float4x4 lightView : VIEW;
float4x4 lightProjection : PROJECTION;
texture colorMap;
texture normalMap;
texture depthMap;
texture prevAccumulation;
texture shadowMap;
//Color map from GBuffer
sampler ColorMap =
sampler_state
{
Texture = <colorMap>;
MipFilter = LINEAR;
MinFilter = LINEAR;
MagFilter = LINEAR;
};
//Normal map from GBuffer
sampler NormalMap =
sampler_state
{
Texture = <normalMap>;
MipFilter = LINEAR;
MinFilter = LINEAR;
MagFilter = LINEAR;
};
//Depth map from GBuffer
sampler DepthMap =
sampler_state
{
Texture = <depthMap>;
MipFilter = LINEAR;
MinFilter = LINEAR;
MagFilter = LINEAR;
};
//The lights shadow map(if it casts)
sampler ShadowMap =
sampler_state
{
Texture = <shadowMap>;
MipFilter = LINEAR;
MinFilter = LINEAR;
MagFilter = LINEAR;
};
//Sample the previously accumulated light map
sampler PrevAccumulation =
sampler_state
{
Texture = <prevAccumulation>;
MipFilter = LINEAR;
MinFilter = LINEAR;
MagFilter = LINEAR;
};
void vsLightMap(float4 iPos : POSITION0,
float2 iUV : TEXCOORD0,
out float4 oPos : POSITION0,
out float2 oUV : TEXCOORD0)
{
oPos = iPos;
oUV = iUV;
}
void psLightMap(float2 iUV : TEXCOORD0,
out float4 oColor : COLOR0)
{
//Read buffer data
float4 mapColor = tex2D(ColorMap, iUV);
float4 mapNormal = tex2D(NormalMap, iUV);
float mapDepth = tex2D(DepthMap, iUV).x;
float4 lightMapPrev = tex2D(PrevAccumulation, iUV);
//Put pixel into world position
//Convert from UV coordinates to clip space
float4 pixelWorldPosition;
pixelWorldPosition.x = (iUV.x * 2.0f) - 1.0f;
pixelWorldPosition.y = ((iUV.y * 2.0f) - 1.0f) * -1;
pixelWorldPosition.z = mapDepth;
pixelWorldPosition.w = 1.0f;
pixelWorldPosition = mul(pixelWorldPosition, cameraViewProjectionInverse);
pixelWorldPosition /= pixelWorldPosition.w;
//Get pixel position from light's view
float4 pixelLightView = mul(pixelWorldPosition, lightView);
float4 pixelLightPos = mul(pixelLightView, lightProjection);
pixelLightPos /= pixelLightPos.w;
//Hard frustum test.
//If position is not visible to the light, shade then return
if(pixelLightPos.x < -1.0f || pixelLightPos.x > 1.0f
|| pixelLightPos.y < -1.0f || pixelLightPos.y > 1.0f
|| pixelLightPos.z < 0.0f || pixelLightPos.z > 1.0f)
{
//TODO once color output has been correctly tested, take the accumulation buffer into consideration
oColor = mapColor * 0.5;
return;
}
//Convert pixel position to UV to sample shadow map
float pixelU = pixelLightPos.x / 2 + 0.5f;
float pixelV = (pixelLightPos.y / -2) + 0.5f;
float2 pixelUV = float2(pixelU, pixelV);
//Sample shadow map to get depth from light view
float lightViewDepth = tex2D(ShadowMap, pixelUV);
//TODO once color output has been correctly tested, take the accumulation buffer into consideration
if(lightViewDepth + 0.001f <= pixelLightPos.z)
{
oColor = mapColor * 0.5;
return;
}
else
{
oColor = mapColor;
return;
}
}
technique SpotLight
{
pass p0
{
VertexShader = compile vs_2_0 vsLightMap();
PixelShader = compile ps_2_0 psLightMap();
}
}
Thanks for any advice =)