2

我正在编写一个基于 PyOpenGL 的 UI 来手动对齐图像。我将我的两个图像显示为带纹理的四边形,在静态参考之上的移动图像。动态图像显示为红色,具有不同的 alpha,即glColor4f(1.,0.,0.,overlay_opacity),而静态图像显示为青色,不透明度等于 1,即glColor4f(0.,1.,1.,1.)。然后用户可以overlay_opacity通过鼠标滚动来改变移动图像和参考图像之间的渐变。

目前我正在使用glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA). 虽然这确实允许我在青色和红色图像之间平滑淡化,但这也意味着当overlay_opacity等于 0.5 时,我只能获得红色和青色图像最大强度的一半,因此结果看起来暗淡而浑浊。如果我使用glBlendFunc(GL_SRC_ALPHA,GL_ONE)我的青色图像,我总是会获得最大强度,所以我不能淡出它。我真正想要的是某种非线性混合,如下面的第三张图所示:

在此处输入图像描述

我想我也许可以在片段着色器中做到这一点,但似乎应该有一种更简单的方法来使用 just 来实现相同的结果glBlendFunc()。我也试过GL_SRC_ALPHA_SATURATE了,这在我的实现中似乎不起作用。

4

2 回答 2

2

快速回答:不,仅使用 OpenGL 调用是不可能的。GL_SRC_ALPHA_SATURATE也不应该做你想做的事,它的 RGB 因子min(Asrc, (1-Adest))在你的情况下可能总是等于Asrc,因为我假设你的目标 alpha 总是 0。

长答案:您最好也是唯一的选择是编写所述片段着色器。为了实现你想要的,你必须使用一些诡计。我建议将覆盖颜色与 alpha 因子预先相乘,然后输出另一个 alpha 值来混合目标颜色。与此类似的等式就足够了:

// Note I cap off the alpha values in both cases to achieve the desired non-linear ramp
float alpha = overlay_opacity * 2.0f;
out = vec4(color.rgb * min(1.0f, alpha), min(1.0f, 2.0f - alpha));

然后使用以下混合函数确保目标颜色也混合:

glBlendFunc(GL_ONE, GL_SRC_ALPHA);

进一步的优化,你注意到我将覆盖不透明度乘以 2 来限制两个 alpha 值。取而代之的是,您可以在将其传递给着色器之前将其预先乘以 2,这将减少每个像素的一些乘法。

希望这能解决你的问题,祝你好运!

于 2013-04-30T22:29:39.233 回答
1

由于您只混合图像,因此您可以使用一个技巧:首先渲染图像 A,调整其颜色。然后你在它上面绘制第二个图像,glBlendFunc(GL_ONE, GL_ONE)使其添加并再次调制颜色。通过使后层和前层的调制颜色遵循您想要的混合曲线,您可以获得您想要的。

于 2013-04-30T23:00:10.183 回答