我的设置:
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,还是需要以不同方式处理着色器中碎片的混合?
答案 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);