问:有没有办法使用默认管道正确混合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的混合工具制作图像.
假设我有这个场景
我想从自定义片段着色器添加深度信息.
现在直观的做法是在没有启用深度测试但是使用glDepthMask(1)和glColorMask(0,0,0,0)的情况下在我的茶壶上绘制四边形.写一些片段gl_FragDepth并丢弃其他一些片段.
if ( gl_FragCoord.x < 100 )
gl_FragDepth = 0.1;
else
discard;
Run Code Online (Sandbox Code Playgroud)
出于某种原因,在NVidia Quadro 600和K5000上它按预期工作,但是在NVidia K3000M和Firepro上(不记得哪一个),我丢弃的片段所覆盖的所有区域都给出了四边形的深度值.
我不能保留丢弃的碎片深度值不加修改吗?
编辑我找到了解决问题的方法.事实证明,正如Andon M. Coleman和Matt Fishman指出的那样,我启用了early_fragment_test但不是因为我启用了它,而是因为我使用了imageStore,imageLoad.
由于我不得不解决这个问题,我只是在"添加深度传递"之前将当前深度缓冲区的内容复制到纹理中.将其分配给统一的sampler2D.这是我的着色器中的代码:
if ( gl_FragCoord.x < 100 )
gl_FragDepth = 0.1;
else
{
gl_FragDepth = texture( depthTex, gl_PointCoord ).r;
color = vec4(0.0,0.0,0.0,0.0);
return;
}
Run Code Online (Sandbox Code Playgroud)
这会写出一个完全透明的像素,其z值保持不变.