【问题标题】:(J)SFML: Gaussian Blur Shader Not Working(J)SFML:高斯模糊着色器不工作
【发布时间】:2015-05-19 19:10:19
【问题描述】:

所以我正在尝试基于this 教程实现一个高斯模糊着色器(用于练习)。我正在将他们的 LWJGL 代码翻译成 JSFML 代码,这有点棘手。

在我的实现中,只有背景精灵可见,鼠标周围不会出现模糊。

我的代码如下,为了便于阅读,去掉了不相关的东西(如异常处理等)。

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();
                }
            }
        }
    }
}

我的片段着色器如下(虽然我确定它是正确的,但教程中的 GLSL 是一样的)

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);
}

在任何人问之前,我只需要片段着色器,因为 SFML 在片段着色器中提供了正确的纹理坐标。

我在执行过程中做错了什么?我怀疑这是我处理 FBO 的方式(在本例中为 RenderTextures)。

【问题讨论】:

    标签: java opengl glsl sfml


    【解决方案1】:

    我注意到你的程序中有两个令人困惑的地方


    第一个是你在里面设置dir(0.0, 0.0)

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

    但在您的着色器程序中,您将其用作乘法因子:

    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;
    ...
    

    4.0*blur*hstep 的结果显然是 0。所以你只是在采样同一点。


    第二件事是你使用高斯的方式。是不是有点像:

    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));
        }
    }
    

    你只是对角线上的采样点

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-05-30
      • 1970-01-01
      • 1970-01-01
      • 2017-10-04
      • 1970-01-01
      • 1970-01-01
      • 2015-09-18
      • 2011-01-27
      相关资源
      最近更新 更多