我正在使用这个问题的答案中描述的方法对一个框架缓冲区对象进行笔画:
opengl - blending with previous contents of framebuffer
该方法正确地将不同的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绘制到屏幕上时,混合和删除prem。alpha工作,当做同样的事情并绘制到FBO时,它会失败。
下面是我读出FBO时产生的(错误的)图像:

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

谢谢你的帮助。
发布于 2016-01-22 13:48:00
我不知道你所说的“摆脱乘积α”是什么意思。如果您想要图片被非预乘,那么您必须手动取消它在JavaScript或在阴影中使用类似的方法。
gl_FragCoord = vec4(color.a > 0. ? color.rgb / color.a : vec3(0), color.a);当您在画布上绘图时,它工作的原因是因为默认情况下,画布期望预先乘以alpha。使用1绘制,ONE_MINUS_SRC_ALPHA使用预乘α绘制,并保持结果预乘以
示例:
Un-premultiplied Red = 0.7 Alpha = 0.2
convert to premultiplied Red = Red * Alpha
Premultiplied Red = 0.14 Alpha = 0.2
blend with ONE,ONE_MINUS_SRC_ALPHA
DstRed = 0.0 DstAlpha = 0.0
newPixelRed = Red(0.14) * ONE + DstRed(0.0) * (1 - Alpha(0.2))
newPixelRed = 0.14 + 0.0 * 0.8
newPixelRed = 0.14
newPixelAlpha = Alpha(0.2) * ONE + DstAlpha(0.0) * (1 - Alpha(0.2))
newPixelAlpha = 0.2 + 0.0 * 0.8
newPixelAlpha = 0.2所以newPixelRed和newPixelAlpha的面积和你画之前的一模一样。
要使newPixelRed回到它的非乘状态,唯一的方法是除以alpha。
newPixelRed = Red(0.14) / Alpha(0.2)
newPixelRed = 0.14 / 0.2
newPixelRed = 0.7 <- The original red before it was premultiplied您只能在着色器或JavaScript中这样做。单靠调合是不行的。
https://stackoverflow.com/questions/34937806
复制相似问题