在OpenGL中平滑可逆的加法/减色亮度混合

时间:2014-06-03 14:59:59

标签: opengl alphablending blending pyopengl

我正在尝试执行一个相当具体的混合操作,但似乎它应该相对简单。我在背景上显示亮度纹理,其alpha值为1.

例如,这可能是另一张图片上的简单棋盘:

enter image description here

我希望纹理根据以下内容线性增加/减少背景的亮度:

(R_b + R_t * w, G_b + G_t * w, B_b + B_t * w, 1.0)

其中*_b是背景像素值(介于0和1之间),*_t是重叠纹理的有符号像素值(介于-1和1之间),w是加权参数也可以在-1和1之间变化。目标是通过改变w的符号和幅度,我可以通过棋盘纹理平滑地改变背景调制的幅度和极性。

为您提供一个图形示例:

enter image description here

使用glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA)只是改变叠加层的alpha值并不能完全符合我的要求,因为我无法使用负的alpha值来反转叠加层的极性。

有没有办法使用固定管道进行这种类型的线性加法/减法混合,或者如果失败,是否可以使用着色器实现这一点?

更新

为了进一步澄清,我添加了一个粗略的PyOpenGL示例,说明了我正在尝试做的事情here

更新2

要完全清楚,如果w > 0,我想增加我棋盘上 white 方块内每个像素的亮度,降低黑色方块内每个像素的亮度。如果w < 0我想做相反的事情。

derhass 的答案非常接近我正在寻找的内容,但只会影响白色方块中的像素,而不会影响黑色方块:

enter image description here

人类在判断绝对亮度方面很糟糕,但如果我将叠加层的颜色设置为红色(glColor4f(1., 0., 0., 0.25)),则差异会更明显:

enter image description here

如您所见,这会导致在白色方块中添加/减去红色,但不会改变黑色方块。

1 个答案:

答案 0 :(得分:1)

我认为你可以使用GL的混合,只要你的w参数不会因每个像素而变化,但只是覆盖纹理的整个绘制调用的全局(正如你的图像所暗示的那样)。您只需根据w

的符号设置混合等式

将混合因子设置为glBlendFunc(GL_SRC_ALPHA,GL_ONE)

  • 对于w&gt; = 0:使用glBlendEquation (GL_FUNC_ADD)并将alpha设置为w

  • 对于w&lt; 0:使用glBlendEquation (GL_FUNC_REVERSE_SUBTRACT)并将alpha设置为-w

如前所述,这也将修改输出的alpha分量,但你希望它是1.0。正如您所说,渲染背景时,您的frambeuffer已经alpha = 1。因此,您可以使用glBlendFuncSeparate (GL_SRC_ALPHA,GL_ONE,GL_ZERO,GL_ONE)与上述公式结合使用,将结果alpha设置为目标中的{,A_b

更新

事实证明,问题中的公式不是理想的行为,并且假设每次绘制调用只需要GL_FUNC_ADD GL_FUNC_REVERSE_SUBTRACT

但是,如果使用浮点颜色缓冲区(ARB_color_buffer_float),则可以使用负的alpha值。

  

如果颜色缓冲区是定点的,则源和的组件   目标值和混合因子各自被钳位到[0; 1]或   [-1; 1]分别用于无符号归一化或有符号归一化   在评估混合方程之前的颜色缓冲区。如果颜色   缓冲区是浮点数,不会发生钳位。由此产生的四个   值将被发送到下一个操作。

请注意,此扩展程序会引入glClampColor()功能,并定义目标GL_CLAMP_READ_COLORGL_CLAMP_VERTEX_COLORGL_CLAMP_FRAGMENT_COLOR。后两者在现代GL中已弃用,仅与已弃用的固定功能管道相关。