View Full Version : VSM Lightbleedingreduction not working

Frischer Hering
01-02-2014, 01:20 PM
Hello there!

If you want to see a screenshot, follow the link. (Had to manipulate it because the forum denied my post otherwise... That's strange)

The light comes from above. As you see, just under the green "leaves" the shadow is that weak, that you can't really see it. Only with more distance the shadow becomes really visible.

The FS that renders into the shadowmap:

layout(location = 0) out vec2 fragmentDepths;

in vec4 pos;

void main(){

float depth = length(pos.xyz);

//First moment is the depth itself.
fragmentDepths.x = depth;
//Compute partial derivatives of depth.
float dx = dFdx(depth);
float dy = dFdy(depth);
//Compute second moment over the pixel extents.
fragmentDepths.y = depth*depth + 0.25*(dx*dx + dy*dy);


The FS of the light computing the actual shadow:

float ChebyshevUpperBound(vec2 moments, float t)

//Surface is fully lit if the current fragment is before the light occluder
if(t < (moments.x)){
return 1.0;

//Compute variance.
float variance = moments.y - (moments.x*moments.x);
variance = max(variance, 0.00002);

//Compute probabilistic upper bound.
float d = t - moments.x;
float p_max = variance / (variance + d*d);

return p_max;

float linstep(float min, float max, float v){
return clamp((v - min) / (max - min), 0.0, 1.0);

float ReduceLightBleeding(float p_max, float Amount)
//Remove the [0, Amount] tail and linearly rescale (Amount, 1].
return linstep(Amount, 1.0, p_max);

float ShadowContribution(vec2 LightTexCoord, float DistanceToLight)
//Read the moments from the variance shadow map.
vec2 Moments = texture(gSamplerShadowmap, LightTexCoord).xy;

//Compute the Chebyshev upper bound.
float pmax = ChebyshevUpperBound(Moments, DistanceToLight);

return ReduceLightBleeding(pmax, 0.8);

// The main function inside the FS

// ...

vec4 shadowCoord = shadowMatrix * vec4(fragmentPos, 1.0); //It's PROJ * VIEW * fragmentPos (which is worldspace coords)
vec3 shadowCoordPostW = (shadowCoord.xyz / shadowCoord.w) * 0.5 + 0.5;
vec2 coord = (shadowCoordPostW.xy);

float compare = length(gLightPosition - fragmentPos);

float shadowFactor = ShadowContribution(coord, compare);

// ...