#define width 4
#define height 4
float sum = 0.0f;
for (int x=-width/2; x < width/2; x++)
for (int y=-height/2; y < height/2; y++)
sum += shadow[i].SampleCmpLevelZero(shadowSampler, input.ShadowPosH[i].xy, input.ShadowPosH[i].z - depthEpsilon, int2(x,y));
sum /= 9.0f;
sum = saturate(sum);
This is how I am doing shadow mapping. I noticed that since I am using a fixed width the shadows get smaller as the frustum of the shadow map increases in size. Before my width and height were 7, giving 49 samples. This means that if the shadow map were so large that only one pixel indicates a shadow I would still sample 48 lit pixels in both directions, causing the shadow to shrink significantly. This led me to conclude that the sampling rate should depend on the width of the camera that generates the shadow map.
The i represents each of many shadow maps for multiple lights.
Someone referenced Sen's paper on Shadow Silhouette Maps. I have tried to implement them as well and let me tell you they are a bit difficult. I still haven't got the silhouette map building correctly. I have also implemented shadow volumes which, aside from generating the volumes in a geometry shader, is pretty straight-forward. Shadow volumes give you incredibly sharp shadow boundaries but the complexity is fundamentally higher than shadow mapping because it is geometry-bound instead of resolution-bound.
Since most people like fake soft shadows from shadow mapping, and since they are fast and relatively easy, I would go with them.