OpenGL es 2.0中的平滑模糊高斯

问题描述:

我尝试使平滑的高斯模糊,但我没有任何想法如何正确地做到这一点。OpenGL es 2.0中的平滑模糊高斯

我试过这样几件事情:

#version 100 

precision mediump float; 

varying vec3 vColor; 
varying vec2 TexCoords; 

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

void main() { 

    vec4 sum = vec4(0.0); 

    vec2 tc = TexCoords; 

    float blur = radius/resolution; 

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


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

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

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

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

但结果是类似的东西: http://i.imgur.com/N6ks3Pw.png

我怎样才能获得更好的效果?

您似乎是在一个正确的方式,但您的vstephstep似乎太大。应该设计一个步骤,以便只需要下一个像素,这意味着它应该是1/size,其大小等于您的情况下的纹理大小。

你只需要几个像素周围不会产生太多的模糊。通常你至少需要一个7x7或9x9的矩阵。你所采取的是有点奇怪,因为这看起来像你只使用当前像素周围的一些对角线值。

在概念的结果应该是这样的

for(horizontalOffset = -radius; horizontalOffset<radius; horizontalOffset += step) { 
    for(verticalOffset = -radius; verticalOffset<radius; verticalOffset += step) { 
     sum += texture2D(texture, textureCoordinate+vec2(horizontalOffset, verticalOffset))*gaussFactorForOffset(sqrt(horizontalOffset*horizontalOffset + verticalOffset*verticalOffset)/radius); 
    } 
} 

这是有点慢,但因为对于具有7个步骤的实例将产生49访问其使得O2质地。您可以通过将其分成2个绘制调用进行优化,其中一个是创建垂直模糊,另一个是水平模糊。这意味着你需要2个着色器,其中一个只有一个垂直循环,另一个只有水平循环。结果是你有14次调用纹理的7个步骤,这样就可以花费20多次绘制调用并在内存中拥有另一个纹理(除非你可以重复使用原始纹理进行第二次绘制调用)。

此外,您还可以在页面上找到大量着色器,例如this one。他们通常没有优化,但他们至少可以让你有一个地方开始。

+0

Hello @Matic对于迟到的回复感到抱歉,我不明白你所说的“你正在服用虽然有点奇怪,因为这看起来像你只使用当前像素周围的一些对角线值”,如果vstep和hstep设置为1,它会做一个对角线(vstep和hstep是模糊高斯的方向)。 对于你的例子,我尝试避免循环,因为我使用GLSL 1.00,它不需要统一(条件表达式的右边必须是常量),但如果你知道解决这个我真的想知道的其他问题。 谢谢 – KeurKeur

+0

你不需要循环,但你需要NxN调用,而不是N.偏移量必须像(-4,-4),(-3,-4)...(+4,-4) ,(-4,-3),(-3,-3)...(+4,+4)。你必须通过一些偏移量访问当前周围的所有像素,在你的情况下是4,这样就可以进行9x9的调用。 –

+0

嗨,谢谢你的工作。它有点慢,但它的工作原理再次感谢:) – KeurKeur