OpenGL模糊

标签 opengl glsl shader

我正在使用 libgdx 并希望制作一个常见的高斯模糊后处理效果。关注 this指南 我在纹理过滤方面遇到了一些问题。这里的图像:
实际图像:
actual image
用半径 = 1 模糊:
blurred with radius = 1
半径为 5 的模糊:
blurred with radius = 5
在最简单的情况下,我只有一个透明的帧缓冲区对象,其中一些对象呈现给它。然后我需要对此应用一些着色器效果,基本上只是模糊然后将结果渲染到屏幕上。我也想调整模糊半径,但如果我将半径设置为大于 1,它看起来会非常粗糙。猜想它应该与一些线性过滤一起使用,但它不在这里。所以我只需要使用软模糊和可配置半径应用相同的效果,也许还有其他一些着色器方面的选项。而且我还尝试将线性过滤显式分配给 FBO 纹理,这不会改变任何内容。
片段着色器:

//"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;
}
class

最佳答案

这不是由于缺少线性插值造成的。该着色器沿每个轴仅执行 9 次纹理提取。您不能期望仅采样 9 次并使用更大的内核获得平滑的模糊,因为您跳过了可能包含重要信息的大量像素。只有 radius = 1已验证。
对于更大的模糊,您需要更大的内核,或者多次应用较小的内核。
如果这太慢,要优化,您可以利用 this article 中的线性插值技术。 .因为线性插值可以让你以一个的价格计算两个相邻纹素之间的任意加权平均值,你可以得到一个等效的过滤器,它只执行 5 次纹理提取而不是 9 次,或者使用 9 次纹理提取来获得大小为 17 的内核。从下采样图像的金字塔中采样也是一种可能性。
顺便说一句,而不是这个冗长的事情:

vec2(tc.x - 4.0*blur*hstep, tc.y - 4.0*blur*vstep)
你可以简单地写:
tc - 4.0*blur*dir
其他 7 行也类似。

关于OpenGL模糊,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64837705/

相关文章:

java - GLSL - 仅对一种纹理产生效果

javascript - Chrome 上的 Three.js 自定义着色器错误 GL_INVALID_OPERATION : Active draw buffers with missing fragment shader outputs

opengl - glsl double 顶点缓冲区

opengl - 在现代 GLSL 中如何将定向光转换为屏幕坐标?

opengl - glBindBuffer 中的 GL_ARRAY_BUFFER 目标意味着什么?

javascript - 从片段着色器恢复像素数据会导致意外行为

opengl - 如何翻转OpenGL的三角形颜色?

opengl - GL_TRIANGLE 风扇说明

c++ - 使用纹理的 alpha channel 作为边界贴图

c++ - 使用 openGL 时立方体未按预期输出