0
votes

So I'm trying to implement a guassian blur shader (for practice) based on this tutorial. I am translating their LWJGL code to JSFML code, and it's a little tricky.

With my implementation, only the background sprite is visible, no blurring occurs around the mouse.

My code is as follows, with irrelevant stuff (like exception handling etc) taken out for readability.

public class ShaderPractice {

    private static final int RTSIZE = 1024;
    private static float radius = 3;
    private static float MAX_BLUR = 3;

    public static void main(String[] args)  {
        RenderWindow rw = new RenderWindow();
        rw.create(new VideoMode(800, 600), "Gaussian Blur!");

        Texture t = new Texture();
        t.loadFromFile(Paths.get("textures/bg.jpg"));

        Sprite bgSprite = new Sprite(t);

        RenderTexture blurTargetA = new RenderTexture();
        blurTargetA.create(RTSIZE, RTSIZE);

        RenderTexture blurTargetB = new RenderTexture();
        blurTargetB.create(RTSIZE, RTSIZE);

        Shader blurShader = new Shader();
        blurShader.loadFromFile(Paths.get("src/shaderpractice/frag.glsl"), Shader.Type.FRAGMENT);

        blurShader.setParameter("u_texture", t);
        blurShader.setParameter("dir", new Vector2f(0, 0));
        blurShader.setParameter("resolution", RTSIZE);
        blurShader.setParameter("radius", radius);


        while (rw.isOpen()) {

            Vector2f mousePos = rw.mapPixelToCoords(Mouse.getPosition());

            blurTargetA.clear();
            blurTargetA.draw(bgSprite);
            blurTargetA.display();

            blurShader.setParameter("dir", new Vector2f(1, 0));

            float mouseXAmt = mousePos.x / rw.getSize().x;
            blurShader.setParameter("radius", mouseXAmt * MAX_BLUR);

            blurTargetB.clear();
            blurTargetB.draw(bgSprite, new RenderStates(blurShader));
            blurTargetB.display();

            blurShader.setParameter("dir", new Vector2f(0, 1));

            float mouseYAmt = (rw.getSize().y-mousePos.y-1) / rw.getSize().y;
            blurShader.setParameter("radius", mouseYAmt * MAX_BLUR);

            rw.draw(bgSprite, new RenderStates(blurShader));

            rw.display();

            for (Event event : rw.pollEvents()) {
                if (event.type == Event.Type.CLOSED) {
                    rw.close();
                }
            }
        }
    }
}

My fragment shader is as follows (although I'm sure it is correct, the GLSL is the same from the tutorial)

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

void main() {

    // RGBA sum
    vec4 sum = vec4(0.0);

    vec2 tc = gl_TexCoord[0].xy;

    float blur = radius/resolution;

    float hstep = dir.x;
    float vstep = dir.y;

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

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

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

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

    gl_FragColor = vec4(sum.rgb, 1.0);
}

Before anyone asks, I only need the fragment shader for this, as SFML provides the correct texture coordinates in the fragment shader.

What am I doing wrong in my implementation? I suspect it's the way I'm handling my FBOs (RenderTextures in this case).

1

1 Answers

0
votes

I noticed two confusing points in your program


The first one is that you set dir (0.0, 0.0) in

blurShader.setParameter("dir", new Vector2f(0, 0));

But in your shader program, you are using it as a multiplication factor:

float hstep = dir.x;
float vstep = dir.y;
...
sum += texture2D(u_texture, vec2(tc.x - 4.0*blur*hstep, tc.y - 4.0*blur*vstep)) * 0.0162162162;
...

And the result of 4.0*blur*hstep is 0, obviously. So you are just sampling the same point.


The second thing is the way you are using Gauss. Isn't it something like:

for(int i=0;i<Num;i++)
{
    for(int j=0;j<Num;j++)
    {
        sum += weight[i][j]*texture2D(texture,vec2(texture_coor[i][j].u,texture_coor[i][j].v));
    }
}

You are just sampling points on the diagonal