解释预乘alpha的工作原理

时间:2015-10-01 13:58:22

标签: rendering opengl-es-2.0 alphablending

有人可以解释为什么使用预乘alpha(和校正混合函数)的渲染看起来与" normal"不同。 alpha,从数学角度来说,那些是相同的吗?

我已经查看了这篇文章,了解预乘alpha:

http://blogs.msdn.com/b/shawnhar/archive/2009/11/06/premultiplied-alpha.aspx

作者还说最终计算是相同的:

"查看常规与预乘alpha的混合方程。如果将此颜色格式转换替换为预乘混合函数,则可以获得常规混合函数,因此无论哪种方式都会产生相同的最终结果。不同之处在于,预乘alpha将(source.rgb * source.a)计算应用为预处理而不是混合硬件。"

我错过了什么吗?为什么结果不同呢?

neshone

3 个答案:

答案 0 :(得分:1)

这是猜测,因为还没有足够的信息来解决它。

应该是一样的。获得不同值的一种常见方法是在预乘和渲染步骤之间使用不同的Gamma校正方法。

我猜你的一个阶段,无论是混合,还是预乘阶段都是用不同的伽玛值完成的。如果使用DirectXTex texconv等工具生成预乘纹理并使用默认的srgb选项进行预乘alpha,那么您的采样器需要是_SRGB格式,渲染目标也应该是_SRGB。如果您正在线性处理它们,那么您可能无法渲染到_SRGB目标或使用伽马校正对纹理进行采样,即使您在采样的相同着色器中进行预乘(取决于3D API并渲染目标设置差异) 。这样做会导致中间调中两种方法之间的alpha显着不同。

请参阅:http://http.developer.nvidia.com/GPUGems3/gpugems3_ch24.html

如果你在photoshop中生成alpha,那么你应该知道几件事。 Photoshop不会以线性OR sRGB格式保存alpha。它将它保存为线性和sRGB之间大约一半的Gamma值。如果你在photoshop中进行预乘,它将正确地计算预乘,但是用错误的斜坡保存结果。如果您生成一个普通的alpha,然后在3d API中将其作为sRGB或LINEAR进行采样,它将会关闭但不会与Photoshop中显示的值相匹配。

如需更深入的回复,我们需要的信息将是。

  • 您使用的是什么3D API。
  • 如何生成和采样纹理
  • 您何时以及如何预先使用alpha。
  • ,最好是显示错误的代码或着色器示例。

答案 1 :(得分:1)

我正在研究为什么会使用Pre vs non-Pre并从Nvidia找到这个有趣的信息

https://developer.nvidia.com/content/alpha-blending-pre-or-not-pre

在使用Pre,而不是Post-Alpha时,它们的具体情况似乎更加精确。

我也读过(我相信这里但是找不到它),做pre-alpha(将Alpha乘以每个RGB值),你将节省时间。我仍然需要找出这是否真实,但似乎有一个理由为什么pre-alpha是首选。

答案 2 :(得分:0)

区别在于过滤。

想象一下,您的纹理只有两个像素,并且正好在两个像素之间的中间对其进行采样。还要假设线性滤波。

Schematically:
R|G|B|A + R|G|B|A = R|G|B|A
non-premultiplied:
1|0|0|1 + 0|1|0|0 = 0.5|0.5|0|0.5
premultiplied:
1|0|0|1 + 0|0|0|0 = 0.5|0|0|0.5

注意绿色通道的差异。 过滤预乘的alpha会产生正确的结果。

请注意,所有这些都与混合无关。