did you ever want more smooth looking shadows from the build in PSSM-Shadow-Cam but you didnt know how to do this?
I will save your time showing how to do this (took me a few hours to get so far)..
This is the standard build in PCF for PSSM-Shadows used by the integrated RTSS-PSSM. It is a simple 2 x 2 Kernel (4 pixel lookups).

And this is the 2x2 kernel * 4 for interpolating (16 pixel lookups) using interpolated depth values:

And this was achived using a 4x4 kernel * 4 for interpolating e.g. 64 texture lookups:

The following snippet works with CG-Shaders and the RTSS on Ogre 1.9 RC. You can easily port the few lines to your favorite shader-language (GLSL, GLSLES, HLSL).
Assuming you got the integrated RTSS PSSM already up and running (if you didnt - just use the search function and u will find threads which describing how to do this):
- Open the SGXLib_IntegratedPSSM.cg file (default path: RTShaderLib/Cg/).
- Now:
replace this function
Code: Select all
//-----------------------------------------------------------------------------
float _SGX_ShadowPCF4(sampler2D shadowMap, float4 shadowMapPos, float2 offset)
{
shadowMapPos = shadowMapPos / shadowMapPos.w;
float2 uv = shadowMapPos.xy;
float3 o = float3(offset, -offset.x) * 0.3f;
// Note: We using 2x2 PCF. Good enough (technique: but looks bad on low resolution :( ) and is a lot faster.
float c = (shadowMapPos.z <= tex2D(shadowMap, uv.xy - o.xy).r) ? 1 : 0; // top left
c += (shadowMapPos.z <= tex2D(shadowMap, uv.xy + o.xy).r) ? 1 : 0; // bottom right
c += (shadowMapPos.z <= tex2D(shadowMap, uv.xy + o.zy).r) ? 1 : 0; // bottom left
c += (shadowMapPos.z <= tex2D(shadowMap, uv.xy - o.zy).r) ? 1 : 0; // top right
return c / 4;
}
Code: Select all
float _SGX_ShadowPCF4(sampler2D shadowMap, float4 shadowMapPos, float2 offset)
{
shadowMapPos = shadowMapPos / shadowMapPos.w;
float2 uv = shadowMapPos.xy;
const int X = 3;
const int Y = 3;
uv.x = uv.x - X / 2 * offset.x;
uv.y = uv.y - Y / 2 * offset.y;
float c = 0;
for(int x = 0; x < X; x++)
{
for(int y = 0; y < Y; y++)
{
float2 position;
position.x = uv.x + float(x) * offset.x;
position.y = uv.y + float(y) * offset.y;
c += texture2DShadowLerp(shadowMap, offset, position, shadowMapPos.z);
//c += (shadowMapPos.z <= tex2D(shadowMap, position).r) ? 1 : 0;
}
}
return c / (float(X) * float(Y));
}
Code: Select all
float texture2DCompare(sampler2D depths, float2 uv, float compare){
float depth = tex2D(depths, uv).r;
return step(compare, depth);
}
float texture2DShadowLerp(sampler2D depths, float2 offset, float2 uv, float compare){
float2 texelSize = offset;
float2 size = 1 / offset;
float2 f = frac(uv * size + 0.5);
float2 centroidUV = floor(uv * size + 0.5) / size;
float lb = texture2DCompare(depths, centroidUV + texelSize * float2(0.0, 0.0), compare);
float lt = texture2DCompare(depths, centroidUV + texelSize * float2(0.0, 1.0), compare);
float rb = texture2DCompare(depths, centroidUV + texelSize * float2(1.0, 0.0), compare);
float rt = texture2DCompare(depths, centroidUV + texelSize * float2(1.0, 1.0), compare);
float a = lerp(lb, lt, f.y);
float b = lerp(rb, rt, f.y);
float c = lerp(a, b, f.x);
return c;
}
- done!
My source was that guide:
http://codeflow.org/entries/2013/feb/15 ... ltered-vsm
