在OpenGL es 2.0中平滑模糊高斯

时间:2017-06-29 15:43:13

标签: opengl-es glsles

我尝试制作一个平滑的高斯模糊,但我不知道如何做到这一点。

我尝试过这样的事情:

#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

如何才能取得更好的成绩呢?

1 个答案:

答案 0 :(得分:1)

您似乎是正确的方式,但您的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个步骤的纹理,这样就可以在另外一个绘制调用和内存中有另一个纹理的情​​况下生成2o(除非你可以重复使用原来的第二个绘制调用)。

您也可以在this one等页面上在线找到大量着色器。它们通常没有经过优化,但它们至少可以为您提供一个起点。