在 glsl 着色器中合成两个 alpha 纹理

Making composite of two alpha textures in a glsl shader

我希望在一个着色器中组合两个纹理,就像您对类似 photoshop 的程序所期望的那样。也就是说,一个纹理叠加在另一个纹理之上,就像分层一样。 两个纹理都有 alpha,结果输出也应该有正确的组合 alpha。

所以目标是;

然而,尽管在谷歌上搜索了公式,我还是无法得到正确的颜色。 在此处使用引用:(https://microsoft.github.io/Win2D/html/PremultipliedAlpha.htm) 例如生成;

(注意灰色 50% 叠加的差异)

着色器代码在libgdx中设置以将其用作混合;

  context.setBlending(true,GL20.GL_SRC_ALPHA ,GL20.GL_ONE_MINUS_SRC_ALPHA);         

我相当确定错误出在我的片段着色器混合中(参见上图中的代码),因为如果我将输入纹理 (A) 直接传递给 gl_FragColor,那么我会得到一个 pixel-perfect A 的颜色匹配,包括它的 alpha。
例如;

gl_FragColor = 反向扩散;

工作正常。

=====

编辑

根据建议,我尝试使用预乘 alpha。

context.setBlending(true,GL20.GL_ONE, GL20.GL_ONE_MINUS_SRC_ALPHA); 

但是,这会产生错误的效果即使着色器刚设置为输出 A

backdiffuse = texture2D(u_backSample2D, vTexCoord);     
backdiffuse=backdiffuse*backdiffuse.a; //convert to premultiply     
gl_FragColor =  backdiffuse; 

我设置的 libgdxs 混合错误吗?这明显太亮了。


解决方案(感谢接受的答案);

 backdiffuse.rgb *= backdiffuse.a; //premultiply source 
 v_backBackColor.rgb *= v_backBackColor.a; //premultiply source 

finalCol.rgb = backdiffuse.rgb + (v_backBackColor.rgb * (1 - backdiffuse.a));       
finalCol.a = backdiffuse.a + (v_backBackColor.a * (1.0 - backdiffuse.a));

如果要使用预乘 alpha 方程,还必须使用适当的混合方程将输出绘制到屏幕:GL_ONE、GL_ONE_MINUS_SRC_ALPHA。

并且目标 alpha 还必须乘以 1 减去源 alpha。所以:

finalCol.a = backDiffuse.a + v_backBackColor * (1.0 - backDiffuse.a);

如果你想使用你当前使用的更典型的混合方程,着色器中的方程会更复杂。如果你查找 alpha compositing on Wikipedia,你可以找到它们。然而,预乘 alpha 是一种首选格式,因为它避免了精灵的抗锯齿边缘上的暗或亮边缘。