OpenGL es 2.0 中的平滑模糊高斯

Smooth blur gaussian in 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 个步骤,这样 2o 的代价是再进行一次绘制调用并在内存中拥有另一个纹理(除非您可以将原始纹理重新用于第二次绘制调用)。

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