c++openglblurshadowsgaussianblur

Gaussian Blur never works correctly


Image of the problem

For some reason every time that I do blur it turns out like this, and I really confused as to why that is. For bloom as well, the blurring was all pixelated and still is as every time I do blur this happens. I really have no idea of what the issue is.

Here is all the code for the blurring of the variance shadow maps that you need.

GaussianBlurVertical fragment shader..

#version 330 core

out vec4 FragColor; //fragment shader output

in vec2 _texcoord;  //input interpolated texture coordinate

uniform sampler2D textureMap; //the input image to blur

//constant kernel values for Gaussian smoothing
const float kernel[]=float[21] (0.000272337,  0.00089296, 0.002583865, 0.00659813,  0.014869116,
                                0.029570767, 0.051898313, 0.080381679, 0.109868729, 0.132526984, 
                                0.14107424,  0.132526984, 0.109868729, 0.080381679, 0.051898313, 
                                0.029570767, 0.014869116, 0.00659813,  0.002583865, 0.00089296, 0.000272337);

void main()
{ 
    //get the inverse of texture size
    vec2 delta = 1.0 / textureSize(textureMap,0);
    vec4 color = vec4(0);
    int  index = 20;

    //go through all neighbors and multiply the kernel value with the obtained 
    //colour from the input image
    for(int i =- 10; i <= 10; i++) {                
        color += kernel[index--] * texture(textureMap, _texcoord + (vec2(0, i * delta.y)));
    } 

    //return the filtered colour as fragment output
    FragColor =  vec4(color.xy,0,0);    
}

GuassianBlurHorizontal fragment shader..

#version 330 core

out vec4 FragColor; //fragment shader output

in vec2 _texcoord;  //input interpolated texture coordinate

//uniform
uniform sampler2D textureMap;   //the input image to blur

//constant kernel values for Gaussian smoothing
const float kernel[]=float[21] (0.000272337,  0.00089296, 0.002583865, 0.00659813,  0.014869116,
                                0.029570767, 0.051898313, 0.080381679, 0.109868729, 0.132526984, 
                                0.14107424,  0.132526984, 0.109868729, 0.080381679, 0.051898313, 
                                0.029570767, 0.014869116, 0.00659813,  0.002583865, 0.00089296, 0.000272337);

void main()
{ 
    //get the inverse of texture size
    vec2 delta = 1.0 / textureSize(textureMap, 0);
    vec4 color = vec4(0);
    int  index = 20;

    //go through all neighbors and multiply the kernel value with the obtained 
    //colour from the input image
    for(int i =- 10; i <= 10; i++) {                
        color += kernel[index--] * texture(textureMap, _texcoord + (vec2(i * delta.x, 0)));
    }

    //return the filtered colour as fragment output
    FragColor =  vec4(color.xy, 0, 0);  
}

Blurring Stage..

glBindFramebuffer(GL_FRAMEBUFFER, _filteredshadowmap_fbo);

glUseProgram(_program_blurH);
glUniform1i(_u_texture_map_h, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, _shadowmap);
renderQuad();

glUseProgram(_program_blurV);
glUniform1i(_u_texture_map_v, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, _shadowmap);
renderQuad();

glBindFramebuffer(GL_FRAMEBUFFER, 0);

Initialising the blur fbo..

// shadowmap blurring
        glGenFramebuffers(1, &_filteredshadowmap_fbo);
        glBindFramebuffer(GL_FRAMEBUFFER, _filteredshadowmap_fbo);

        glGenTextures(1, &_filtered_shadowmap);

        glBindTexture(GL_TEXTURE_2D, _filtered_shadowmap);

        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_BORDER);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);

        glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);

        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, SHADOW_QUALITY, SHADOW_QUALITY, 0, GL_RGBA, GL_FLOAT, NULL);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _filtered_shadowmap, 0);

        GLenum status2 = glCheckFramebufferStatus(GL_FRAMEBUFFER);
        status2 != GL_FRAMEBUFFER_COMPLETE ? std::cerr << "Unable to create FBO" << std::endl : std::cout << "FBOs Were successful" << std::endl;

        glBindFramebuffer(GL_FRAMEBUFFER, 0);

Solution

  • In general your gaussian blur shader works, but you use it the wrong way.

    The gaussian blur shader in your question is a 2 pass shader. The 1st pass blurs vertical and the 2nd pass blurs horizontal.
    To do this, 2 target textures are of need. The vertical blur pass read the source texture and writes to an "intermediate" texture. The horizontal blur reads the "intermediate" texture and writes to the target texture.

    Create 2 framebuffers and 2 texture attachments, in the same way as you did it your question. Of course it is possible to use 1 frame buffer with 2 texture attachments and switching the texture attachments between the passes, too. In fact the texture attachment of one framebuffer can be changed between the passes, too.
    In my answer I decided to create 2 framebuffer, because the code of your question can be reused completly.

    Create a frambuffer object _intermediateshadowmap_fbo and an attached texture object _intermediate_shadowmap as you did it for _filteredshadowmap_fbo and _filtered_shadowmap in the question:

    glGenFramebuffers(1, &_intermediateshadowmap_fbo);
    glBindFramebuffer(GL_FRAMEBUFFER, _intermediateshadowmap_fbo);
    
    glGenTextures(1, &_intermediate_shadowmap);
    
    .....
    

    And create the 2nd frambuffer object _filteredshadowmap_fbo and the 2nd texture object _filtered_shadowmap:

    glGenFramebuffers(1, &_filteredshadowmap_fbo);
    glBindFramebuffer(GL_FRAMEBUFFER, _filteredshadowmap_fbo);
    
    glGenTextures(1, &_filtered_shadowmap);
    
    .....
    

    To create the blured texture the following has to be done:


    glViewport( 0, 0, SHADOW_QUALITY, SHADOW_QUALITY );
    glBindFramebuffer(GL_FRAMEBUFFER, _intermediateshadowmap_fbo);
    
    glUseProgram(_program_blurH);
    glUniform1i(_u_texture_map_h, 0);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, _shadowmap);
    renderQuad();
    
    glBindFramebuffer(GL_FRAMEBUFFER, _filteredshadowmap_fbo);
    
    glUseProgram(_program_blurV);
    glUniform1i(_u_texture_map_v, 0);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, _intermediate_shadowmap);
    renderQuad();
    
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glViewport(0, 0, window_width, window_height);