Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
619 views
in Technique[技术] by (71.8m points)

glsl - OpenGl blurring

I'm using libgdx and want to make a common Gaussian blur post-processing effect. Following this guide I faced some issues with texture filtering. Here the images:

actual image:

actual image

blurred with radius = 1:

blurred with radius = 1

blurred with radius = 5:

blurred with radius = 5

In the simplest case, I just have a transparent frame buffer object with some objects rendered to it. Then I need to apply some shader effects to this, basically only blur and then render the result to the screen. I also want to adjust the blur radius, but if I set the radius to more than 1 it becomes looking very rough. Guess it should be used with some linear filtering, but it isn't here. So I just need the same effect applied with a soft blur and configurable radius, maybe some other shader-sided options. And I've also tried to explicitly assign Linear filtering to FBO textures, which doesn't change anything.

Fragment shader:

//"in" attributes from our vertex shader
varying vec4 vColor;
varying vec2 vTexCoord;

//declare uniforms
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);
    
    //our original texcoord for this fragment
    vec2 tc = vTexCoord;
    
    //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 += 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 = vColor * sum;
}

The full class

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This is not caused by a lack of linear interpolation. This shader is doing only 9 texture fetches along each axis. You can't expect to sample only 9 times and get a smooth blur with a larger kernel, because you are skipping over a lot of pixels which might contain important information. Only radius = 1 is valid.

For a larger blur, you either need a larger kernel, or apply the smaller kernel several times.

To optimize if this gets too slow, you can leverage the linear interpolation technique from this article. Because linear interpolation lets you compute an arbitrary weighted average between two adjacent texels for the price of one, you can get an equivalent filter that performs just 5 texture fetches instead of 9, or use 9 texture fetches to get a kernel of size 17. Cleverly sampling from a pyramid of downsampled images is also a possibility.

By the way, instead of this verbose thing:

vec2(tc.x - 4.0*blur*hstep, tc.y - 4.0*blur*vstep)

You can simply write:

tc - 4.0*blur*dir

And similar for the other 7 lines.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...