If you want some samples you can download my deferred Engine and check out the DeferredDirectionaLight shader, i have some different techniques in there.
The PCF I gave you is a bit blocky. If you want a better variant (more expensive) use this
A good input for the iSqrtSamples would be between 3 and 7
// Calculates the shadow term using PCF with edge tap smoothing
float CalcShadowTermSoftPCF(float fLightDepth, float ndotl, float2 vTexCoord, int iSqrtSamples)
{
float fShadowTerm = 0.0f;
float variableBias = clamp(0.0005 * tan(acos(ndotl)), 0.00001, DepthBias);
//float variableBias = (-cos(ndotl) + 1)*0.02;
//variableBias = DepthBias;
float shadowMapSize = ShadowMapSize.x;
float fRadius = iSqrtSamples - 1; //mad(iSqrtSamples, 0.5, -0.5);//(iSqrtSamples - 1.0f) / 2;
for (float y = -fRadius; y <= fRadius; y++)
{
for (float x = -fRadius; x <= fRadius; x++)
{
float2 vOffset = 0;
vOffset = float2(x, y);
vOffset /= shadowMapSize;
//vOffset *= 2;
//vOffset /= variableBias*200;
float2 vSamplePoint = vTexCoord + vOffset;
float fDepth = ShadowMap.Sample(ShadowMapSampler, vSamplePoint).x;
float fSample = (fLightDepth <= fDepth + variableBias);
// Edge tap smoothing
float xWeight = 1;
float yWeight = 1;
if (x == -fRadius)
xWeight = 1 - frac(vTexCoord.x * shadowMapSize);
else if (x == fRadius)
xWeight = frac(vTexCoord.x * shadowMapSize);
if (y == -fRadius)
yWeight = 1 - frac(vTexCoord.y * shadowMapSize);
else if (y == fRadius)
yWeight = frac(vTexCoord.y * shadowMapSize);
fShadowTerm += fSample * xWeight * yWeight;
}
}
fShadowTerm /= (fRadius*fRadius*4);
return fShadowTerm;
}
Or you can modify the original PCF with some edge tapping
float CalcShadowTermPCF(float light_space_depth, float ndotl, float2 shadow_coord)
{
float shadow_term = 0;
//float2 v_lerps = frac(ShadowMapSize * shadow_coord);
float variableBias = GetVariableBias(ndotl);
//safe to assume it's a square
float size = 1.0f / 2048;
float samples[5];
samples[0] = (light_space_depth - variableBias < 1-ShadowMap.SampleLevel(pointSampler, shadow_coord, 0).r);
samples[1] = (light_space_depth - variableBias < 1 - ShadowMap.SampleLevel(pointSampler, shadow_coord + float2(size, 0), 0).r) * frac(shadow_coord.x * ShadowMapSize);
samples[2] = (light_space_depth - variableBias < 1 - ShadowMap.SampleLevel(pointSampler, shadow_coord + float2(0, size), 0).r) * frac(shadow_coord.y * ShadowMapSize);
samples[3] = (light_space_depth - variableBias < 1 - ShadowMap.SampleLevel(pointSampler, shadow_coord - float2(size, 0), 0).r) * (1-frac(shadow_coord.x * ShadowMapSize));
samples[4] = (light_space_depth - variableBias < 1 - ShadowMap.SampleLevel(pointSampler, shadow_coord - float2(0, size), 0).r) * (1 - frac(shadow_coord.y * ShadowMapSize));
shadow_term = (samples[0] + samples[1] + samples[2] + samples[3] + samples[4]) / 5.0;
//shadow_term = lerp(lerp(samples[0],samples[1],v_lerps.x),lerp(samples[2],samples[3],v_lerps.x),v_lerps.y);
return shadow_term;
}