I'm trying to implement exponential shadow mapping (ESM) into my rendering engine but I'm facing some problems: I can get to see some shadows only if the exponential multiplier is less than 0, and the image becomes very dark.
I was already using Variance Shadow Maps, so I adapted my code to use ESM.
I've changed the fragment shader used to compute the shadow map like this:
#version 150 core uniform float Exponential; // Exponential multiplier term of the ESM equation out float FragColor; float map_01(float x, float v0, float v1) { return (x - v0) / (v1 - v0); } void main() { float depthDivisor = (1.0 / gl_FragCoord.z); float mappedDivisor = map_01(depthDivisor, 0.1f, 20.0f); // Since my light is a directional light I force the near and far planes to 0.1 and 20.0 FragColor = exp(Exponential * mappedDivisor); // VSM float depth = gl_FragCoord.z; // VSM float dx = dFdx(depth); // VSM float dy = dFdy(depth); // VSM float moment2 = depth * depth + 0.25 * (dx * dx + dy * dy); // VSM FragColor = vec4(depth, moment2, 0.0, 1.0); }
I've kept the same vertex shader for the shadow map:
in vec3 _position; uniform mat4 ProjectionViewMatrix; // Projection-View matrix of the light layout(std140) uniform MOD { mat4 AModelMatrix[20]; }; void main() { gl_Position = ProjectionViewMatrix * AModelMatrix[gl_InstanceID] * vec4(_position, 1.0); }
And I've changed the my directional light fragment shader to become like this:
uniform mat4 InverseProjectionViewMatrix; // Inverse of the camera projection-view matrix uniform float Exponential; // Exponential multiplier term of the ESM equation (same as shadow map fragment shader) uniform mat4 ProjectionViewMatrix; // Light projection view matrix void main() { vec3 genPos = vec3((gl_FragCoord.x * InverseScreenSize.x), (gl_FragCoord.y * InverseScreenSize.y), 0.0f); genPos.z = texture(PrepassBuffer_DepthMap, genPos.xy).r; vec4 clip = InverseProjectionViewMatrix * vec4(genPos * 2.0f - 1.0f, 1.0f); vec3 pos = clip.xyz / clip.w; vec4 shadowCoord = ProjectionViewMatrix * vec4(pos, 1.0f); shadowCoord /= shadowCoord.w; shadowCoord.xyz = shadowCoord.xyz * vec3(0.5f, 0.5f, 0.5f) + vec3(0.5f, 0.5f, 0.5f); float occluder = texture(DILShadowMap, shadowCoord.xy).r; float reciever = map_01(shadowCoord.z, 0.1f, 20.0f); float shadowAmount = saturate(occluder * exp(-Exponential * reciever)); ... }
A couple of images to show the problem.
This is the result I get with Exponential set to 1.0 (no shadows at all):
This is the result I get with Exponential set to -30.0 (starting to see some shadows):
This is the result I get with the exact same coputations of the position (same vertex shaders basically) but with the variance shadow maps equation:
The only things I've changed from the algorithm I've found are these two lines in the shadow map fragment shader and in the directional light fragment shader:
// Shadow map fragment shader float depthDivisor = (1.0 / gl_FragCoord.z); // <- changed gl_FragCoord.z (originally was gl_FragCoord.w) // Directional light fragment shader float reciever = map_01(shadowCoord.z, 0.1f, 20.0f); // <- changed shadowCoord.z (originally was shadowCoord.w)
I've made these two changes because the W component was always 1.0, and it didn't seem correct to me to use W when the depth is stored into the Z component.
0 comments:
Post a Comment