1
\$\begingroup\$

im using a lightmap to achieve a 2d lighting effect in OpenGL with dynamic shadows and to make them soft I use the gaussian blur. However I noticed one problem : When I use big blur ratio, it has some strange behaviour like in this picture:

enter image description here

It lookes like a problem with UV coordinates but I checked and everything should be fine. This is the shader:

#version 440

in vec4 fragmentColor;
in vec2 fragmentUV;

out vec4 color;

uniform sampler2D u_texture;
uniform float resolution;
uniform float radius;
uniform vec2 dir;

void main() {

    //this will be our RGBA sum
    vec4 sum = vec4(0.0);

    vec2 tc = fragmentUV;

    //the amount to blur, i.e. how far off center to sample from 
    //1.0 -> blur by one pixel
    //2.0 -> blur by two pixels, etc.
    float blur = radius/resolution; 

    //the direction of our blur
    //(1.0, 0.0) -> x-axis blur
    //(0.0, 1.0) -> y-axis blur
    float hstep = dir.x;
    float vstep = dir.y;

    //apply blurring, using a 9-tap filter with predefined gaussian weights

    sum += texture(u_texture, vec2(tc.x - 4.0*blur*hstep, tc.y - 4.0*blur*vstep)) * 0.0162162162;
    sum += texture(u_texture, vec2(tc.x - 3.0*blur*hstep, tc.y - 3.0*blur*vstep)) * 0.0540540541;
    sum += texture(u_texture, vec2(tc.x - 2.0*blur*hstep, tc.y - 2.0*blur*vstep)) * 0.1216216216;
    sum += texture(u_texture, vec2(tc.x - 1.0*blur*hstep, tc.y - 1.0*blur*vstep)) * 0.1945945946;

    sum += texture(u_texture, vec2(tc.x, tc.y)) * 0.2270270270;

    sum += texture(u_texture, vec2(tc.x + 1.0*blur*hstep, tc.y + 1.0*blur*vstep)) * 0.1945945946;
    sum += texture(u_texture, vec2(tc.x + 2.0*blur*hstep, tc.y + 2.0*blur*vstep)) * 0.1216216216;
    sum += texture(u_texture, vec2(tc.x + 3.0*blur*hstep, tc.y + 3.0*blur*vstep)) * 0.0540540541;
    sum += texture(u_texture, vec2(tc.x + 4.0*blur*hstep, tc.y + 4.0*blur*vstep)) * 0.0162162162;

    //discard alpha for our simple demo, multiply by vertex color and return
    color = 1. * vec4(sum.rgb, 1.0);
}

At the picture i used only the horizontal blur, for checking purposes. I create the lightmap in following order:

  1. Render lights and ambient color to framebufferA
  2. Render texture from framebufferA to framebufferB using horizontal blur
  3. Render texture from framebufferB to framebufferA using vertical blur

I can post aditional code, however i dont know if the problem is with framebuffers. I tried it without the bluring and it works perfectly, it happens only when I use blur. Thanks in advance

Edit1 I noticed that it is happening also on normal textures(not framebuffers textures). According to the comment, i´m including the code for texture wrapping:

    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);

As for my UV coordinates, they were initialized and i didnt change them during runtime, they were set for normal rectangle.

I´ve tried the CLAMP_TO_EDGE wrap option (when i try CLAMP_TO_BORDER it disappears and i see just black texture), for normal textures it looked like it was solved but when I applied it also to the framebuffers texture it looked like this: enter image description here

Here is my code for the framebuffer creation:

void Framebuffer::init(vec2 screenRes) {

        _screenRes = screenRes;

        //Generate the framebuffer ID
        if (_framebufferID != 0)
            glDeleteFramebuffers(1,&_framebufferID);

        if (_textureID != 0)
            glDeleteTextures(1, &_textureID);

        glGenFramebuffers(1, &_framebufferID);
        assert::checkWrongValue(_framebufferID, GL_FALSE, "Failed to generate framebuffer ID");

        //Bind it while we configure it
        glBindFramebuffer(GL_FRAMEBUFFER, _framebufferID);

        //Generation of the texture
        glGenTextures(1, &_textureID);

        assert::checkWrongValue(_textureID, GL_FALSE, "Failed to generate texture ID for framebuffer");

        //Bind it
        glBindTexture(GL_TEXTURE_2D, _textureID);

        //Actually create a space
        glTexImage2D(GL_TEXTURE_2D,
                    0,
                    GL_RGBA,
                    _screenRes.x,
                    _screenRes.y,
                    0,
                    GL_RGBA,
                    GL_UNSIGNED_BYTE,
                    NULL);

        //Wrapping
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

        //Set it as a framebuffer texture
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _textureID, 0);

        //Creating render object
        glGenRenderbuffers(1, &_renderObjectID);
        assert::checkWrongValue(_renderObjectID, GL_FALSE, "Failed to generate render object ID for framebuffer");

        //Bind it
        glBindRenderbuffer(GL_RENDERBUFFER, _renderObjectID);

        //Configure it
        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, _screenRes.x, _screenRes.y);

        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _renderObjectID);

        //Check the success
        assert::checkValue(glCheckFramebufferStatus(GL_FRAMEBUFFER), GL_FRAMEBUFFER_COMPLETE, "Failed to create a framebuffer");

        //Back to the default framebuffer
        glBindRenderbuffer(GL_RENDERBUFFER, 0);

        glBindFramebuffer(GL_FRAMEBUFFER, 0);
    }
\$\endgroup\$
  • 1
    \$\begingroup\$ How are you handling edges? Are you clamping to edge, clamping to transparent black, or something else? I'd check your texture wrapping in the "S" direction. \$\endgroup\$ – user1118321 Apr 1 '18 at 5:03
  • \$\begingroup\$ I´ve added an edit to my question with desired code. \$\endgroup\$ – Pins Apr 1 '18 at 9:35
3
\$\begingroup\$

It looks to me like the problem is related to your texture wrapping. Originally you had GL_TEXTURE_WRAP_REPEAT, which is clearly wrong. You can even see in the original image on the right side, some of the light has bled over. I believe that GL_TEXTURE_WRAP_CLAMP_TO_EDGE is probably what you want. I think something else is going wrong with your second image which is causing the texture to repeat a single row of pixels vertically.

It seems odd that you're setting the hstep and vstep to 0 or 1. You're using GL_TEXTURE_2D which means that texture coordinates are in the range 0-1. You would need to make the step for a single pixel be 1/image width or 1/image height. Otherwise you're always getting the first or last pixel when you sample. That might explain the vertical problem you're seeing in the second image.

\$\endgroup\$
  • \$\begingroup\$ What do you mean by adding additional step for the texture coordinate fix? You mean to apply it to gl_FragCoord before I apply the blur functions? Or to hstep and vstep? \$\endgroup\$ – Pins Apr 1 '18 at 15:29
  • \$\begingroup\$ I would apply it to hstep and vstep. You must already be doing it to hstep because it looks correct. And I'm guessing you were doing it to vstep originally, because this problem didn't exist in the original image. \$\endgroup\$ – user1118321 Apr 1 '18 at 16:09
  • \$\begingroup\$ Actually I was not doing anything, the shader I posted is the one Im using. Can be the problem the fact that I´m using framebuffer texture and something is missing? Because on normal textures(not framebuffers) it works fine, even when I use GL_REPEAT wrap option. \$\endgroup\$ – Pins Apr 1 '18 at 17:04
  • \$\begingroup\$ I also tried to clamp it in the shader but didn´t help. \$\endgroup\$ – Pins Apr 1 '18 at 17:20
  • \$\begingroup\$ "Can be the problem the fact that I´m using framebuffer texture and something is missing?" Yes, there can be problems with that. You have to ensure that the previous draw operations have completed before you use the output of one operation as the input to another operation. That's generally accomplished by using either a glFlush() or using glFenceSync or related calls. \$\endgroup\$ – user1118321 Apr 1 '18 at 22:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.