如何在glsl着色器中模糊透明纹理?

时间:2015-05-04 21:16:44

标签: glsl webgl

我的设置:

Ping-ponging RGBA FBO,以及两个用于模糊的着色器:水平和垂直着色器。想象一下,我想要模糊一个红色矩形。

混合功能如下:

_gl.blendEquationSeparate(_gl.FUNC_ADD, _gl.FUNC_ADD);
_gl.blendFuncSeparate(_gl.SRC_ALPHA, _gl.ONE_MINUS_SRC_ALPHA, _gl.ONE, _gl.ONE_MINUS_SRC_ALPHA);

在我的模糊着色器中,我添加了几个这样的片段:

vec4 color = texture2D(u_image, v_tex_coord + vec2(x, y) * u_amount) * weight;

问题:

模糊在不透明纹理上工作正常,但随着它混合越来越透明,颜色变成黑色,好像所有东西都混合了黑色背景。我清晰的颜色是0,0,0,0,所以这是有道理的。

问题:

我如何获得真正变为透明红色的模糊效果,而不是当alpha变为零时混合了越来越多的黑色?

我基本上想要在Photoshop中在完全透明的背景上模糊某些东西时。我是否需要预乘的FBO,还是需要以不同方式处理着色器中碎片的混合?

2 个答案:

答案 0 :(得分:2)

要将模糊应用于透明纹理,您需要使用alpha来校正。有一个像素的简化公式:

resultColor = (sum of pixels of input image) * 1 / K;

通常K是内核大小。

如果模糊透明纹理,则需要累积alpha并将其用作K.

resultAlpha = (sum of alpha pixels of input image);
resultColor = (sum of pixels of input image) * 1 / resultAlpha;
resultAlpha = resultAlpha * 1 / K;

对于此公式,如果您模糊4个像素,其中一个是不透明度而另一个是透明的,则结果像素的颜色将相同,但alpha将小4倍。

在我的示例中,所有通道的值都为0到1。

答案 1 :(得分:0)

我通过在任何地方使用预乘alpha来解决它。

习惯Photoshop的工作方式,我花了一些时间来掌握这个概念。这感觉有点违反直觉,但this explanation from Tom Forsyth给了我很多帮助。

我的所有着色器现在将RGB值乘以它的A:

gl_FragColor = clr.rgb * alpha;

我正在使用不同的混合模式来完成这项工作:

_gl.blendEquation(_gl.FUNC_ADD); _gl.blendFunc(_gl.ONE, _gl.ONE_MINUS_SRC_ALPHA);

我必须确保我的.PNG图像纹理也是预乘的。我是这样做的:

_gl.pixelStorei(_gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);