OpenGL默认管道alpha混合对alpha组件没有任何意义

Jea*_*chu 11 opengl alpha blending glsl

问:有没有办法使用默认管道正确混合Alpha组件?

问题:我正在将半透明表面绘制到纹理中,然后我想将该纹理blit到主框架后缓冲区中.通常,当您使用直接的alpha混合进行透明度或抗锯齿处理时,它会将颜色分量混合到后台缓冲区中(通过deafult没有alpha通道).

但是,当混合到具有alpha分量的纹理时,通常的GL_SRC_ALPHA,GL_ONE_MINUS_DST_ALHPA不会正确地混合"alpha"组件:

在此输入图像描述

注意红色和蓝色圆圈边缘的死星上有问题的区域; alpha组件应该是完全不透明的.请注意,RGB组件是预期的blendend.

因此,我使用GL_DST_ALPHA作为我的dst alpha缩放因子,使用BlendFunc的不同设置并且最接近我想要的设置.

在此输入图像描述

这种方法仍然存在问题,因为混合两个具有50%不透明度的表面应该得到75%不透明度的组合表面.但是使用OpenGL默认公式,得到(0.5*0.5)+(0.5*0.5)= 0.5.更令人不安的是,如果我有2个不透明度为40%的表面,我会得到一个不透明的表面:(.4*.4)+(.4*.4)= 0.32.

实数公式(1 - (1 - srcAlpha)*(1 - dstAlpha))意味着我可以在alpha分量的混合方程中使用GL_FUNC_MULT而不是GL_FUNC_ADD.不幸的是,这不存在.

所以我放弃并试图使用着色器做一个解决方案.如果您渲染的纹理也是您读取的纹理,这会变得非常复杂.特别是如果渲染多个半透明表面.

我正在寻找我尚未尝试的替代解决方案.欢迎任何想法.

编辑:我也尝试了GL_ONE作为src和dst缩放因子.这使得alpha组件太不透明,因为1*.5 + 1*.5将得到1作为结果alpha.让我想知道GL_ONE和GL_DST_ALPHA是否会给出更好的结果.

已解决:在得知答案(见评论)后,我发现多个参考文献都在讨论相同的解决方案:

https://www.opengl.org/discussion_boards/showthread.php/167554-FBO-and-blending

https://forum.openframeworks.cc/t/weird-problem-rendering-semi-transparent-image-to-fbo/2215/10

https://www.opengl.org/wiki/Blending

我觉得自己找不到那些傻事我觉得很愚蠢

ps:我使用Anders Riggelsen的混合工具制作图像.

Hol*_*Cat 7

使用完美混合的标准技术

glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
Run Code Online (Sandbox Code Playgroud)

使用预乘纹理(或颜色,如果你没有纹理).

预乘基本上意味着color.rgb *= color.a在加载纹理时应用纹理(或在着色器中将相同的方程应用于最终颜色).


您可以使用以下混合模式在预先复制的情况下获得相同的结果:

glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
Run Code Online (Sandbox Code Playgroud)

请记住,两种混合模式都会产生预乘的输出.