用Premultiplied Alpha读出一个FBO

时间:2016-01-22 02:04:12

标签: javascript opengl webgl

我正在使用此问题答案中描述的方法将画笔笔划绘制到帧缓冲对象:

opengl - blending with previous contents of framebuffer

此方法正确地alpha - 将不同的OpenGL绘图操作混合到一个FBO中,并确保alpha保持正确。

使用

glBlendFuncSeparate(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA,GL_ONE,GL_ONE_MINUS_SRC_ALPHA);

将OpenGL绘图操作(在我的情况下是笔刷笔触)混合到FBO中并使用

glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA);

将最终的FBO(在我的情况下是类似Photoshop的图层)绘制回屏幕,该屏幕删除了方法中使用的预乘alpha。当FBO上映到屏幕时,这对我来说很好。

但是,当我想读出FBO的内容时,我无法摆脱预乘的alpha。即当我使用

glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA);

将图层绘制到另一个FBO中,而不是使用glReadPixel()来读出此FBO的内容,内容仍然是预乘的。

换句话说,当我将FBO绘制到屏幕上时,混合并移除前景。 alpha工作,当做同样的事情和绘制到FBO时,它失败了。

当我读出FBO时,这是(错误的)图像:

enter image description here

以下是将图层直接绘制到屏幕时的正确结果:

enter image description here

感谢您的帮助。

1 个答案:

答案 0 :(得分:5)

我不确定你的意思"摆脱预乘的alpha"。如果您希望图片不被预乘,那么您必须手动取消它在JavaScript或着色器中的类似

newPixelRed

绘制到画布时它起作用的原因是因为默认情况下画布需要预乘alpha。用ONE渲染,ONE_MINUS_SRC_ALPHA用预乘alpha绘制并保持结果预乘

示例:

newPixelAlpha

因此,newPixelRednewPixelRed = Red(0.14) / Alpha(0.2) newPixelRed = 0.14 / 0.2 newPixelRed = 0.7 <- The original red before it was premultiplied 区域与您绘制之前完全相同。

<table id="jTable"> <tr> <td>No</td> <td>Competition</td> <td>John</td> <td>Adam</td> <td>Robert</td> <td>Paul</td> </tr> <tr> <td>1</td> <td>Swimming</td> <td>1:30</td> <td>2:05</td> <td>1:15</td> <td>1:41</td> </tr> <tr> <td>2</td> <td>Running</td> <td>15:30</td> <td>14:10</td> <td>15:45</td> <td>16:00</td> </tr> <tr> <td>3</td> <td>Shooting</td> <td>70%</td> <td>55%</td> <td>90%</td> <td>88%</td> </tr> <tr> <td>Total</td> <td>Blablabla</td> <td>1000</td> <td>1000</td> <td>1000</td> <td>1000</td> </tr> </table> 回到其未经预测的状态的唯一方法是除以alpha

$('#jTable').find('tr:gt(0):not(:last)').slideToggle();

您只能在着色器或JavaScript中执行此操作。单独混合不会做到这一点。

相关问题