2015-05-19 19 views
0

Итак, я пытаюсь реализовать гуассианский шейдер размытия (для практики) на основе урока this. Я переводил их код LWJGL в код JSFML, и это немного сложно.(J) SFML: Gaussian Blur Shader не работает

С моей реализацией видно только фоновый спрайт, вокруг мыши не происходит размытия.

Мой код выглядит следующим образом, с нерелевантными вещами (например, обработка исключений и т. Д.), Выведенными для удобства чтения.

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 обеспечивает правильные координаты текстуры в шейдере фрагмента.

Что я делаю неправильно в моей реализации? Я подозреваю, что это то, как я обрабатываю свои FBOs (RenderTextures в этом случае).

ответ

0

я заметил две запутанные моменты в вашей программе


Первый является то, что вы установили 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)); 
    } 
} 

Вы только выборки точек по диагонали