我听说预乘alpha可以让您获得顺序独立的透明度,但是当我坐下来进行数学运算时,它似乎不起作用。

这是不正确的,还是我正在做某事

我使用的公式是:

$ out_ {rgba} = in_ {rgba} + out_ {rgba} *(1-in_a)$

其中$ in $是预乘alpha。换句话说,采用RGBA中的“正常”颜色,我将RGB乘以a。 30%不透明的白色将以(1、1、1、0.3)开始,但变为预乘alpha的(0.3、0.3、0.3、0.3)。

得出错误答案后用手,我在下面编写了C ++程序,但仍然得到错误的结果。

执行后:

$ out1 =(0.738,0.913,0.3,1.0)\\
out2 =(0.738,0.875,0.113,1.0)$

谁能解释原因?

#include <array>

typedef std::array<float, 4> RGBA;

void PremultiplyAlpha (RGBA& rgba)
{
    rgba[0] *= rgba[3];
    rgba[1] *= rgba[3];
    rgba[2] *= rgba[3];
}

RGBA BlendPremultipliedAlpha (const RGBA& dest, const RGBA& src)
{
    RGBA ret;
    ret[0] = src[0] + dest[0] * (1.0f - src[3]);
    ret[1] = src[1] + dest[1] * (1.0f - src[3]);
    ret[2] = src[2] + dest[2] * (1.0f - src[3]);
    ret[3] = src[3] + dest[3] * (1.0f - src[3]);
    return ret;
}

int main(int argc, char **argv)
{
    RGBA greenGround = { 0.0f, 1.0f, 0.0f, 1.0f };
    PremultiplyAlpha(greenGround);

    RGBA red25PercentOpaque = { 1.0f, 0.0f, 0.0f, 0.25f };
    PremultiplyAlpha(red25PercentOpaque);

    RGBA white30PercentOpaque = { 1.0f, 1.0f, 1.0f, 0.3f };
    PremultiplyAlpha(white30PercentOpaque);

    RGBA yellow50PercentOpaque = { 1.0f, 1.0f, 0.0f, 0.5f };
    PremultiplyAlpha(yellow50PercentOpaque);

    // one way
    RGBA out1;
    {
        // start with the green ground and blend in 25% opaque red
        out1 = greenGround;
        out1 = BlendPremultipliedAlpha(out1, red25PercentOpaque);

        // then blend in 50% yellow
        out1 = BlendPremultipliedAlpha(out1, yellow50PercentOpaque);

        // then blend in 30% opaque white
        out1 = BlendPremultipliedAlpha(out1, white30PercentOpaque);
    }

    // other way
    RGBA out2;
    {
        // start with the green ground and blend in 30% opaque white
        out2 = greenGround;
        out2 = BlendPremultipliedAlpha(out2, white30PercentOpaque);

        // then blend in 25% red
        out2 = BlendPremultipliedAlpha(out2, red25PercentOpaque);

        // then blend in 50% yellow
        out2 = BlendPremultipliedAlpha(out2, yellow50PercentOpaque);
    }

    return 0;
}


#1 楼

预乘alpha本身不会为您提供顺序独立的透明度,不。

本页讨论如何将其用作顺序独立的透明度解决方案的一部分:http://casual-effects.blogspot。 com / 2015/03 / implemented-weighted-blended-order.html

预乘alpha的其他好处包括:


包含alpha的纹理的更好的mipmap: https://developer.nvidia.com/content/alpha-blending-pre-or-not-pre
能够在单个纹理内进行透明度和添加混合,而无需更改渲染状态或发出多次绘制通话:http://amindforeverprogramming.blogspot.com/2013/07/why-alpha-premultiplied-colour-blending.html
能够表示更逼真的照明情况,例如不透明不会导致这种情况。 t总是意味着透明:http://distantsoulsdev.blogspot.com.ar/2013/02/premultiplied-alpha-online-interactive.html
能够更加自然/正确/ e轻松合成具有alpha通道的图像。
能够通过图像处理(模糊/卷积)获得更好的结果。没有黑晕:https://stackoverflow.com/questions/4854839/how-to-use-pre-multiplied-during-image-convolution-to-solve-alpha-bleed-problem
预乘alpha也可以透明要从前到后而不是从前到后绘制的对象,可能会节省像素写入。


#2 楼

根据预乘alpha混合的证明,有一个假设,即“操作员必须遵守关联规则。”
因此,它可能导致处理顺序的混乱。

因此,不是交换规则,blend(a,b)与blend(b,a)不同。

因此,
blend(blend(a,b),c)返回相同blend(a,blend(b,c))的值。
但是,
blend(blend(a,b),c)不会返回相同的blend(blend(b,a)的值, c)像你的例子。

#3 楼

吉姆·布林(Jim Blinn)的合成文章艾伦(Alan)也解释了为什么预乘是对透明图像进行任何过滤的正确方法。