OpenGL Alpha混合

x4shl7ld  于 2022-09-26  发布在  其他
关注(0)|答案(2)|浏览(177)

我已经找到了5349574673页关于Alpha混合的页面,但我仍然无法得到想要的结果。我正在尝试使用OpenGL使gif/png文件正确显示(具有透明度/半透明度)。

以下是我的初始化代码:

glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); //I've seen this on most tutorials
glDisable(GL_DEPTH_TEST); //it's a 2D game
//...loading matrices and so on

我确信图像是透明的,并且加载正确。
GlBlendFunc(GL_One,GL_One);工作,但我不知道它是否在Alpha通道上做了什么,因为它会渲染为Black=>混合工作
GlColor4f(1f,1f,1f,0.3f);效果很好,我可以画透明的东西

附注:我正在使用这个示例http://lwjgl.org/wiki/index.php?title=Space_Invaders_Example_Game来学习

编辑我使用了用GIMP和其他纹理加载器编码的其他纹理,现在它工作得很好。

3bygqnnd

3bygqnnd1#

您的混合设置是正确的。然而,为了使混合起作用,纹理必须包含Alpha通道,当然,该通道的值是正确的。然后,必须通过图像加载过程来保存Alpha通道数据。我们可以看一下图像加载和纹理生成代码吗?

blpfk2vs

blpfk2vs2#

Alpha混合公式的主要问题是源/目标/结果颜色的存储方式。我们有两种情况:Alpha预乘(r、g、b通道与Alpha通道相乘);非Alpha预乘(r、g、b不相乘)。您必须确保使用哪种格式来使用正确的混合配方。Alpha预乘是在将一些东西渲染到屏幕时经常使用的,它允许使用更简单和更快的混合公式。

我收集了下面所有的基本案例,但首先是一些信息:

  • 什么是源/目标:如果你以Photoshop的方式思考,你可以将目标视为底层,源和顶层。
  • 混合函数:它是着色器线性内插函数(也称为LERP)。来自OpenGL参考:Mix使用A在X和Y之间执行线性内插:mix(x, y, a) = x * (1 - a) + y * a。根据我的经验,在GPU碎片着色器中使用mix版本比使用标准公式要快一点。
  • 所有公式都适用于浮点颜色值(从0.0到1.0)
  • 如果要将不透明度用于源颜色,则只需将src.a乘以不透明度src.a *= opacity
  • 在可以被0除以的公式中,您可能需要添加一个类似以下条件的“if”条件:
result.a = <formula for alpha>;
if (result.a == 0.0) {
    result.rgb = dest.rgb;
} else {
    result.rgb = <formula for rgb>;
}

公式如下:

1.源、目的、结果未预乘

result.a = dest.a * (1.0 - src.a) + src.a;
result.rgb = (dest.rgb * dest.a * (1.0 - src.a) + src.rgb * src.a) / result.a;  // division by 0

或使用MIX函数:

result.a = mix(dest.rgb, 1.0, src.a);
result.rgb = mix(dest.rgb * dest.a, src.rgb, src.a) / result.a;  // division by 0!!!!

OpenGL Blend功能:

not possible

2.源、目的、结果都是预乘

result.a = dest.a * (1.0 - src.a) + src.a;
result.rgb = dest.rgb * (1.0 - src.a) + src.rgb;

混合版本:

result.a = mix(dest.rgb, 1.0, src.a);
result.rgb = dest.rgb * (1.0 - src.a) + src.rgb; // "mix" version not available

OpenGL Blend功能:

glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);

3.目的地、结果预乘、源未预乘

result.a = dest.a * (1.0 - src.a) + src.a;
result.rgb = dest.rgb * (1.0 - src.a) + src.rgb * src.a;

混合版本:

result.a = mix(dest.rgb, 1.0, src.a);
result.rgb = mix(dest.rgb, src.rgb, src.a);

OpenGL Blend功能:

glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);

4.Destination不透明(Dest.a=1.0),因此结果不透明,源不预乘

result.rgb = dest.rgb * (1.0 - src.a) + src.rgb * src.a;
result.a = 1.0;

混合版本:

result.rgb = mix(dest.rgb, src.rgb, src.a);
result.a = 1.0;

OpenGL Blend功能:

glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);

相关问题