opengl:非线性加色混色

时间:2013-04-30 21:42:18

标签: opengl alphablending blending pyopengl

我正在编写一个基于PyOpenGL的UI来手动对齐图像。我将我的两个图像显示为纹理四边形,静态参考顶部的运动图像。运动图像以红色显示,具有不同的α,即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)我总是得到青色图像的最大强度,所以我不能淡出它。我真正想要的是某种非线性混合,看起来像下面的第三张图:

enter image description here

我想我也许可以在片段着色器中执行此操作,但似乎应该有一种更简单的方法来使用glBlendFunc()来实现相同的结果。我也试过GL_SRC_ALPHA_SATURATE,这在我的实现中似乎没有用。

2 个答案:

答案 0 :(得分: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,这将削减每个像素的一些乘法。

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

答案 1 :(得分:1)

由于你只混合了图像,你可以通过一个技巧来实现:首先渲染图像A,调制其颜色。然后使用glBlendFunc(GL_ONE, GL_ONE)在其上绘制第二个图像,使其添加并再次调整颜色。通过使背面和正面层的调制颜色符合您想要的混合曲线,您可以获得所需的颜色。