View Full Version : Am I missing something with ESM?

02-11-2018, 02:19 AM
I've been trying to implement Exponential Shadow Maps, and while it is working great for spotlights and point lights, I'm having trouble getting a good result for directional lights with cascaded shadow maps.

For example, here's a screenshot of what I'm working with:


As you can see, in general objects which should be fully shadowed are only partially shadowed (i.e. the shadow at the base of the "character") and there is a major disjunction between the level of shadow in the different cascades.

I'm calculating the exponential shadow map value like so:

// shadowmap texture value output
uniform float lightExponentialConstant;
layout (location = 0) out float shadow;

void main (void) {
// depth in shadow space as a percentage between near and far plane
float mappedDepth = map_01(gl_FragCoord.z / gl_FragCoord.w, lightNearPlane, lightFarPlane);
shadow = exp(lightExponentialConstant * mappedDepth);

And then visibility is computed with the following function in the lighting shader:

float computeFragmentVisibility(vec3 worldSpacePosition, ShadowMap shadow, sampler2D shadowmapSampler) {

mat4 shadowBias = mat4(
0.5, 0.0, 0.0, 0.0,
0.0, 0.5, 0.0, 0.0,
0.0, 0.0, 0.5, 0.0,
0.5, 0.5, 0.5, 1.0

// near & far planes used for shadow map
float lightNearPlane = shadow.shadowSpaceNearPlane;
float lightFarPlane = shadow.shadowSpaceFarPlane;
// projection * view used for shadowmap
mat4 shadowSpaceProjection = shadow.shadowSpaceProjection;

vec4 shadowCoord = shadowBias * shadowSpaceProjection * vec4(worldSpacePosition, 1.0);
float occluder = texture(shadowmapSampler, shadowCoord.xy/shadowCoord.w).r;
float reciever = map_01(shadowCoord.z/shadowCoord.w, lightNearPlane, lightFarPlane);

float visibility = clamp(occluder * exp(-lightExponentialConstant * reciever), 0.0, 1.0);


So like I said before this method seems to work great for other light sources, but it's failing for directional lights. I can improve the results a bit using a higher lightExponentialConstant value, but I still get a noticeable break between cascades. Also I think I am using quite a high constant parameter value in general - most of the examples I've seen have it around 10, and I need to be up around 80 to get shadows that aren't totally anemic.

Is there some "gotcha" I'm missing? Maybe there is something different about shadowmaps from and ortho projection?

Any advice would be much appreciated, I've already spent a couple days banging my head against this trying to get a nice result.