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
我怎样才能获得更好的效果?
答
您似乎是在一个正确的方式,但您的vstep
和hstep
似乎太大。应该设计一个步骤,以便只需要下一个像素,这意味着它应该是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。他们通常没有优化,但他们至少可以让你有一个地方开始。
Hello @Matic对于迟到的回复感到抱歉,我不明白你所说的“你正在服用虽然有点奇怪,因为这看起来像你只使用当前像素周围的一些对角线值”,如果vstep和hstep设置为1,它会做一个对角线(vstep和hstep是模糊高斯的方向)。 对于你的例子,我尝试避免循环,因为我使用GLSL 1.00,它不需要统一(条件表达式的右边必须是常量),但如果你知道解决这个我真的想知道的其他问题。 谢谢 – KeurKeur
你不需要循环,但你需要NxN调用,而不是N.偏移量必须像(-4,-4),(-3,-4)...(+4,-4) ,(-4,-3),(-3,-3)...(+4,+4)。你必须通过一些偏移量访问当前周围的所有像素,在你的情况下是4,这样就可以进行9x9的调用。 –
嗨,谢谢你的工作。它有点慢,但它的工作原理再次感谢:) – KeurKeur