Дает ли предварительно умноженная альфа прозрачность, независимую от порядка?

8

Я слышал, что предварительно умноженная альфа дает вам прозрачность, независимую от порядка, но когда я сажусь и делаю математику, она, похоже, не работает.

Это неправда или я что-то делаю неправильно?

Формула, которую я использую:

outrgba=inrgba+outrgba(1ina)

где inэто предварительно умноженная альфа. Другими словами, принимая «нормальный» цвет в RGBA, я умножаю RGB на a. 30% непрозрачного белого цвета начинаются как (1, 1, 1, 0,3), но становятся (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;
}
Алан Вульф
источник

Ответы:

9

Предварительно умноженная альфа сама по себе не обеспечивает прозрачность заказа, нет.

На этой странице рассказывается о том, как его можно использовать как часть независимого от заказа решения прозрачности: http://casual-effects.blogspot.com/2015/03/implemented-weighted-blended-order.html

Другие преимущества предварительно умноженного альфа включают:

Алан Вульф
источник
5

Из доказательства предварительно умноженного альфа-смешения делается предположение, что «оператор должен соблюдать ассоциативное правило». Таким образом, это может привести к путанице в порядке процесса.

Поскольку это не коммутативное правило, 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), как в вашем примере.

Вуххён Ким
источник