OpenGL Alpha 混合

发布于 2024-12-11 17:54:53 字数 755 浏览 7 评论 0原文

我已经找到了 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 通道上执行任何操作,因为它会呈现为黑色 =>混合工程
glColor4f(1f,1f,1f,0.3f);工作正常,我可以画透明的

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

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

I've found 5349574673 pages on alpha blending and I still can't get the desired result.
I'm trying to make gif/png files display properly (WITH transparency/translucency) using opengl.

Here's my initialization bit:

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

I am SURE the images have transparency, and are loaded properly.
glBlendFunc(GL_ONE, GL_ONE); works but I can't tell if it's doing anything on the alpha channel since it would render as black => blending works
glColor4f(1f,1f,1f,0.3f); works fine, I can draw transparent stuff

P.S. I'm using this example http://lwjgl.org/wiki/index.php?title=Space_Invaders_Example_Game for learning

EDIT
I used other textures made encoded with GIMP and other texture loaders and it now works fine.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

强辩 2024-12-18 17:54:53

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

Your blending setup is correct. However for blending to work the texture must contain an alpha channel, properly valued of course. And then the alpha channel data must be preserved by the image loading process. May we see the image loading and texture generation code, please?

⒈起吃苦の倖褔 2024-12-18 17:54:53

Alpha 混合公式的主要问题是如何存储源/目标/结果颜色。我们有 2 种情况: alpha 预乘(r、g、b 通道乘以 alpha 通道);非 alpha 预乘(r、g、b 不相乘)。您必须确保使用哪些格式才能使用正确的混合公式。
在将某些内容渲染到屏幕上时经常使用 alpha 预乘,它允许使用更简单、更快的混合公式。

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

  • 什么是源/目标:如果您以“Photoshop”方式思考,您可以将目标视为底层,源和顶层。
  • mix 函数:它是着色器线性插值函数(也称为 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

或使用混合函数:

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 混合函数:

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混合函数:

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 混合函数:

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

4。目标不透明 (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 混合函数:

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

The main problem with alpha blending formula is how source/destination/result colors are stored. We have 2 cases: alpha-premultiplied (r,g,b channels are multiplied by alpha channel); not-alpha-premultiplied (r,g,b are not multiplied). You have to ensure which formats are used to use correct blending formulas.
alpha-premultiplication is often used when rendering something to the screen, it allows to use simpler and faster blending formula.

I gathered all basic cases below, but first some informations:

  • what is source/destination: if you think in "Photoshop" way you can treat destination as bottom layer, and source and top layer.
  • mix functions: it is shader linear interpolation function (also know as lerp). From OpenGL reference: mix performs a linear interpolation between X and Y using A to weight between them: mix(x, y, a) = x * (1 - a) + y * a. From my experience i can say mix version is a bit faster than standard formula when using it in gpu fragment shaders.
  • all formulas are for float color values (from 0.0 to 1.0)
  • if you want to use opacity for source color you have to just multiply src.a by the opacity src.a *= opacity
  • in formulas where division by 0 can happen you probably have to add an "if" condition like this:
result.a = <formula for alpha>;
if (result.a == 0.0) {
    result.rgb = dest.rgb;
} else {
    result.rgb = <formula for rgb>;
}

So here are the formulas:

1. Source, Destination, Result are not premultiplied

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

or using mix function:

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 functions:

not possible

2. Source, Destination, Result are all premultiplied

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

mix version:

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 functions:

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

3. Destination, Result premultiplied, Source not premultiplied

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

mix version:

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

OpenGL blend functions:

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 is opaque (dest.a = 1.0) so Result is opaque, Source non premultiplied

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

mix version:

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

OpenGL blend functions:

glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文