我怎样才能最好地在 opengl 中实现权重归一化混合操作?

How can I best implement a weight-normalizing blend operation in opengl?

假设我有一个 RGBA 格式的源颜色 (sr, sb, sg, sa),同样还有一个目标颜色 (dr, db, dg , da), 假设所有分量都在 [0.0, 1.0].

p = (sa)/(sa+da),且q = da/(sa+da)。请注意 p+q = 1.0。如果 sa 和 da 都为 0.0,请执行任何操作。

我想在 opengl 中实现混合,以便混合结果 =

(p*sr + q*dr, p*sg + q*dg, p*sb + q*db, sa+da).

(或者更严格一点,在 https://www.opengl.org/sdk/docs/man/html/glBlendFunc.xhtml 之后,我希望 f_R、f_G 和 f_B 是 src 的 p 或q 代表 dst;并且 f_A = 1。)

例如,在 (sa+da) == 1.0 的特殊情况下,我可以使用 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);但我专门尝试处理总和不为 1.0 的 alpha 值。 (这就是为什么我称它为 'weight-normalizing' - 我想将 src 和 dst alpha 视为需要归一化为线性组合系数的权重)。

您可以假设我可以完全控制传递给 opengl 的数据、代码渲染以及顶点和片段着色器。我的目标是 WebGL,但总的来说我也只是好奇。

我能想到的最好的方法是混合一个,一个,将所有 src rgb 值预乘以 alpha,然后在最后进行第二次除以 alpha。但恐怕我会以这种方式牺牲很多颜色深度,尤其是在各种 alpha 值很小的情况下。

我不相信标准混合方程可以做到这一点。至少我想不出办法了。

但是,使用 OpenGL 可以很容易地做到这一点。混合可能只是错误的工具。我会将您目前描述的 "source" 和 "destination" 都作为片段着色器的输入纹理。然后,您可以随心所欲地混合和组合它们。

假设您有两个要按照您描述的方式组合的纹理。现在你可能有这样的东西:

  1. 绑定纹理 1.
  2. 渲染到默认帧缓冲区,采样当前绑定的纹理。
  3. 设置花式混合。
  4. 绑定纹理 2.
  5. 渲染到默认帧缓冲区,采样当前绑定的纹理。

你可以做什么:

  1. 将纹理 1 绑定到纹理单元 0。
  2. 将纹理 2 绑定到纹理单元 1。
  3. 渲染到默认帧缓冲区,对两个绑定纹理进行采样。

现在您在着色器代码中获得了两种纹理的值,并且可以应用任何类型的逻辑和数学来计算组合颜色。

如果您的原始数据不是来自纹理,而是渲染的结果,同样的事情也适用。假设您在渲染过程中有两个部分,您希望以您描述的方式组合它们:

  1. 将纹理 1 作为渲染目标附加到 FBO。
  2. 渲染第一部分内容。
  3. 将纹理 2 作为渲染目标附加到 FBO。
  4. 呈现内容的第二部分。
  5. 将纹理 1 绑定到纹理单元 0。
  6. 将纹理 2 绑定到纹理单元 1。
  7. 渲染到默认帧缓冲区,对两个绑定纹理进行采样。