PDA

View Full Version : Variance shadow mapping with Gaussian blur



blaidd
03-31-2016, 12:43 AM
I'm trying to implement VSM with a vertical and horizontal gaussian blur in a defferred renderer. So far VSM works but I can't blur the shadows.
the following shows how I create the shadow maps,



glBindFramebuffer(GL_FRAMEBUFFER, shadow_fbo_);
GLfloat borderColor[] = { 1.0, 1.0, 1.0, 1.0 };

for (unsigned int i = 0; i < scene_->getAllSpotLights().size(); i++)
{
SceneModel::SpotLight spotlight = scene_->getAllSpotLights()[i];

if (spotlight.getCastShadow())
{
GLuint shadow_map_tex;
glGenTextures(1, &shadow_map_tex);
glBindTexture(GL_TEXTURE_2D, shadow_map_tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, SHADOW_WIDTH, SHADOW_HEIGHT, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
//insert texture into map with corresponding light index
shadow_maps_.insert(std::pair<int, GLuint>(i, shadow_map_tex));
}
}
glBindTexture(GL_TEXTURE_2D, shadow_map_blurred_tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, SHADOW_WIDTH, SHADOW_HEIGHT, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);

glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, shadow_maps_[0], 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, shadow_map_blurred_tex, 0);

//rbo depth attatchment
glBindRenderbuffer(GL_RENDERBUFFER, shadow_rbo_);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT32, SHADOW_WIDTH, SHADOW_HEIGHT);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, shadow_rbo_);

GLenum buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
glDrawBuffers(2, buffers);


The following code shows how I am attempting to blur the shadows:



glUseProgram(shadow_blur_program_);
glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT);

float blur_amount = 1.0;
for (std::pair<int, GLuint> pair : shadow_maps_)
{
//blur horizontally
glDrawBuffer(GL_COLOR_ATTACHMENT1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

//use shadow map texture for input and write to blurred shadow texture
glActiveTexture(GL_TEXTURE4);
glBindTexture(GL_TEXTURE_2D, pair.second);
glUniform1i(glGetUniformLocation(shadow_blur_progr am_, "sampler_world_shadow"), 4);

glm::vec2 blur = glm::vec2((1.0 / SHADOW_WIDTH) * blur_amount, 0.0);
glUniform2fv(glGetUniformLocation(shadow_blur_prog ram_, "blurScale"), 1, glm::value_ptr(blur));

glBindVertexArray(light_quad_mesh_.vao);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);


//blur vertically
glDrawBuffer(GL_COLOR_ATTACHMENT0);

//use blurred texture for input and write back to shadow texture
glActiveTexture(GL_TEXTURE5);
glBindTexture(GL_TEXTURE_2D, shadow_map_blurred_tex);
glUniform1i(glGetUniformLocation(shadow_blur_progr am_, "sampler_world_shadow"), 4);

blur = glm::vec2(0.0, (1.0 / SHADOW_WIDTH) * blur_amount);
glUniform2fv(glGetUniformLocation(shadow_blur_prog ram_, "blurScale"), 1, glm::value_ptr(blur));

glBindVertexArray(light_quad_mesh_.vao);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
//switch viewport back
glViewport(0, 0, viewport_size[2], viewport_size[3]);


Below is the shadow blur vertex shader:



#version 330

in vec2 vertex_position;

void main(void)
{
gl_Position = vec4(vertex_position, 0, 1);
}


and the fragment shader:



#version 330

uniform sampler2D sampler_world_shadow;
uniform vec2 blurScale;

layout(location = 0)out vec4 fragment_colour;

void main()
{
vec4 colour = vec4(0.0);
ivec2 coord = ivec2(gl_FragCoord.xy);

colour += texture2D(sampler_world_shadow, coord + vec2(-3.0 * blurScale.x, -3.0 * blurScale.y)) * 0.015625;
colour += texture2D(sampler_world_shadow, coord + vec2(-2.0 * blurScale.x, -2.0 * blurScale.y)) * 0.09375;
colour += texture2D(sampler_world_shadow, coord + vec2(-1.0 * blurScale.x, -1.0 * blurScale.y)) * 0.234375;
colour += texture2D(sampler_world_shadow, coord + vec2(0.0, 0.0)) * 0.3125;
colour += texture2D(sampler_world_shadow, coord + vec2(1.0 * blurScale.x, 1.0 * blurScale.y)) * 0.234375;
colour += texture2D(sampler_world_shadow, coord + vec2(2.0 * blurScale.x, 2.0 * blurScale.y)) * 0.09375;
colour += texture2D(sampler_world_shadow, coord + vec2(3.0 * blurScale.x, 3.0 * blurScale.y)) * 0.015625;

fragment_colour = vec4(colour.xy, 0.0, 0.0);
}

Shadows are created but no blurring seems to be done!

I haven't included the vsm shader code as it works to create shadows. The attachment should show a shadow.
any help would be appreciated.
if more code is needed let me know.