L'alpha prémultiplié donne-t-il une transparence indépendante de l'ordre?

8

J'ai entendu dire que l'alpha pré-multiplié vous donne une transparence indépendante de l'ordre, mais quand je m'assois et fais le calcul, cela ne semble pas fonctionner.

Est-ce faux ou est-ce que je fais quelque chose de mal?

La formule que j'utilise est:

outrgbune=jenrgbune+outrgbune(1-jenune)

jenest un alpha prémultiplié. En d'autres termes, en prenant une couleur "normale" en RGBA, je multiplie RGB par a. 30% de blanc opaque commencerait par (1, 1, 1, 0,3) mais deviendrait (0,3, 0,3, 0,3, 0,3) comme alpha prémultiplié.

Après avoir obtenu les mauvaises réponses lors de l'élaboration à la main, j'ai écrit le programme C ++ ci-dessous et j'obtiens toujours les mauvais résultats.

Après exécution:

out1=(0,738,0,913,0,3,1.0)out2=(0,738,0,875,0,113,1.0)

Quelqu'un peut-il expliquer pourquoi?

#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;
}
Alan Wolfe
la source

Réponses:

9

L'alpha prémultiplié lui-même ne vous donne pas de transparence indépendante de l'ordre, non.

Cette page explique comment il peut être utilisé dans le cadre d'une solution de transparence indépendante des commandes: http://casual-effects.blogspot.com/2015/03/implemented-weighted-blended-order.html

Les autres avantages de l'alpha prémultiplié comprennent:

Alan Wolfe
la source
5

De la preuve d'un mélange alpha prémultiplié, il y a une hypothèse selon laquelle «l'opérateur doit respecter la règle associative». Cela peut donc entraîner une confusion dans l'ordre de traitement.

Puisque ce n'est pas la règle commutative, le mélange (a, b) n'est pas le même que le mélange (b, a).

Par conséquent, blend (blend (a, b), c) renvoie la même valeur de blend (a, blend (b, c)). mais, blend (blend (a, b), c) ne renvoie pas la même valeur de blend (blend (b, a), c) que votre exemple.

Woohyun Kim
la source