Hello,
After attempting to implement variance shadow mapping I've run into a problem and absolutely no idea what is causing it. Here is a picture of what is going on:
The shadow seems to get lighter the closer it is to the occluder. Its very strange and the implementations / tutorials that I've looked at don't seem to have the same problem and haven't touched on how to fix it. Of course this image isn't enough, so here is the relevant code:
How I create the frame buffer for the shadow map:
frameBuffer bufferToReturn;
bufferToReturn.x = x;
bufferToReturn.y = y;
glGenFramebuffers(1, &bufferToReturn.bufferID);
glBindFramebuffer(GL_FRAMEBUFFER, bufferToReturn.bufferID);
glGenTextures(1, &bufferToReturn.texture);
glBindTexture(GL_TEXTURE_2D, bufferToReturn.texture);
if (shadow == false)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA_FLOAT32_APPLE, x, y, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, 0);
else glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, x, y, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glBindTexture(GL_TEXTURE_2D, 0);
glGenTextures(1, &bufferToReturn.depth);
glBindTexture(GL_TEXTURE_2D, bufferToReturn.depth);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, x, y, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
if (shadow == true)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
glBindTexture(GL_TEXTURE_2D, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, bufferToReturn.texture, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, bufferToReturn.depth, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
return bufferToReturn;
And here is the shader code for rendering the depth. I've only rendered out the depth to attempt to be memory conservative and just compute the moments in the lighting shader.
varying vec4 position;
void main()
{
//get the depth
float depth = position.z/position.w;
gl_FragColor = vec4(depth, 0.0, 0.0, 1.0);
}
Lastly the lighting code, at least the parts of it that deal with shadow.
uniform sampler2D positionMap;
uniform sampler2D normalMap;
uniform sampler2D albedoMap;
uniform sampler2D shadowMap;
varying vec2 texcoord;
uniform mat4 shadowMatrix;
float chebyshevUpperBound(vec3 coord)
{
float depth = texture2D(shadowMap,coord.xy).r;
vec2 moments = vec2(depth,depth*depth);
//if we are closer than the depth map, we are lit
if (coord.z <= moments.x)
return 1.0;
float variance = moments.y - (moments.x*moments.x);
variance = max(variance,0.0005);
float momentdistance = coord.z - moments.x;
float p_max = variance / (variance + momentdistance*momentdistance);
return p_max;
}
void main()
{
//get all the G-buffer information
vec3 normal = normalize(texture2D(normalMap,texcoord)).rgb;
vec4 color = (texture2D(albedoMap,texcoord));
vec3 position = (texture2D(positionMap,texcoord)).rgb;
vec4 lightPosition = shadowMatrix*vec4(position,1.0);
lightPosition /= lightPosition.w;
float shadow = chebyshevUpperBound(lightPosition.xyz);
gl_FragColor = vec4(((diffuselight+specular)*shadow)+ambient,color.w);
}
Any input is greatly appreciated and hopefully may be able to help anybody else in the future with the same problem.