我正在使用此问题答案中描述的方法将画笔笔划绘制到帧缓冲对象:
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时,这是(错误的)图像:
以下是将图层直接绘制到屏幕时的正确结果:
感谢您的帮助。
答案 0 :(得分:5)
我不确定你的意思"摆脱预乘的alpha"。如果您希望图片不被预乘,那么您必须手动取消它在JavaScript或着色器中的类似
newPixelRed
绘制到画布时它起作用的原因是因为默认情况下画布需要预乘alpha。用ONE渲染,ONE_MINUS_SRC_ALPHA用预乘alpha绘制并保持结果预乘
示例:
newPixelAlpha
因此,newPixelRed
和newPixelRed = 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中执行此操作。单独混合不会做到这一点。