在 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 是一种首选格式,因为它避免了精灵的抗锯齿边缘上的暗或亮边缘。
我希望在一个着色器中组合两个纹理,就像您对类似 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 是一种首选格式,因为它避免了精灵的抗锯齿边缘上的暗或亮边缘。