I'm trying to implement a simple shadow map , but as you can see in the screenshot, there are some strange z-artifacts,
here is the shader :
float4x4 _lightViewProjMat;
shared float4x4 _worldViewProjMat;
float4x4 _textureMat; // transform projection into shadow map texture coords
texture _shadowMapTexture;
texture _diffuseTexture;
sampler _shadowMapSampler = sampler_state
{
texture = (_shadowMapTexture);
MipFilter = Linear;
MinFilter = Linear;
MagFilter = Linear;
AddressU = Clamp;
AddressV = Clamp;
};
sampler _diffuseSampler = sampler_state
{
texture = (_diffuseTexture);
MipFilter = Linear;
MinFilter = Linear;
MagFilter = Linear;
AddressU = Wrap;
AddressV = Wrap;
};
struct VS_OUTPUT_SMAP
{
float4 p : POSITION;
float depth : TEXCOORD0;
};
struct VS_OUTPUT_UNLIT
{
float4 p : POSITION;
float4 t : TEXCOORD0;
float2 coord : TEXCOORD1;
};
/////////////////////////////////////////////////////////
VS_OUTPUT_SMAP hmrVS_ShadowMap( float4 pos : POSITION )
{
VS_OUTPUT_SMAP output = (VS_OUTPUT_SMAP)0;
output.p = mul( pos, _lightViewProjMat );
output.depth = output.p.z;
return output;
}
float4 hmrPS_ShadowMap( VS_OUTPUT_SMAP input ) : COLOR
{
return float4( input.depth, input.depth, input.depth, 1.0f );
}
///////////////////////////////////////////////////////
VS_OUTPUT_UNLIT hmrVS_Unlit( float4 pos : POSITION, float2 coord : TEXCOORD0 )
{
VS_OUTPUT_UNLIT output = (VS_OUTPUT_UNLIT)0;
output.p = mul( pos, _worldViewProjMat );
output.t = mul( pos, _textureMat );
output.coord = coord;
return output;
}
float4 hmrPS_Unlit( VS_OUTPUT_UNLIT input ) : COLOR
{
// 3x3 PCF filtering
float4 texCoords[9];
float texelSize = 1.0f / 100.0f;
// 4 3 5
// 1 0 2
// 7 6 8
texCoords[0] = input.t;
texCoords[1] = input.t + float4( -texelSize, 0.0f, 0.0f, 0.0f );
texCoords[2] = input.t + float4( texelSize, 0.0f, 0.0f, 0.0f );
texCoords[3] = input.t + float4( 0.0f, -texelSize, 0.0f, 0.0f );
texCoords[6] = input.t + float4( 0.0f, texelSize, 0.0f, 0.0f );
texCoords[4] = input.t + float4( -texelSize, -texelSize, 0.0f, 0.0f );
texCoords[5] = input.t + float4( texelSize, -texelSize, 0.0f, 0.0f );
texCoords[7] = input.t + float4( -texelSize, texelSize, 0.0f, 0.0f );
texCoords[8] = input.t + float4( texelSize, texelSize, 0.0f, 0.0f );
float shadowTerm = 0.0f;
for( int i = 0; i < 9; i++ ) {
float A = tex2Dproj( _shadowMapSampler, texCoords ).r;
float B = (input.t.z - 0.1f);
// compare A (shadow map) to the new one (B) to see if it is shadowed
shadowTerm += A < B ? 0.2f : 1.0f;
}
shadowTerm /= 9.0f;
float4 diffuse = tex2D( _diffuseSampler, input.coord );
return shadowTerm * diffuse;
}
the Shadow buffer is R32F
the "_lightViewProjMat" is set to -> World * LightView * LightProj .
the "_worldViewProjMat" is set to -> World * CamView * CamProj
the "_textureMat" is set to ->
float offs = 0.5f + (0.5f / 512.0f /*size of the shadow buffer*/);
D3DXMATRIX texMat( 0.5f, 0.0f, 0.0f, 0.0f,
0.0f, -0.5f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
offs, offs, 0.0f, 1.0f );
_textureMat = World * LightView * LightProj * texMat;
I think the problem is the "float B = input.t.z - 0.1f" line which causes floating point precision errors, but don't know how to solve it , any ideas ?