Blend mode with alpha

Viewed 334

I am trying to replicate blend modes. Currently I have recreated a screen blend mode, but it doesn't seem to work really well with transparent images.

I have two textures

Image 1 (Foreground)

enter image description here

Image 2 (Background)

enter image description here

And the result I get is this

enter image description here

The Compute Shader code

#pragma kernel Blend

RWTexture2D<float4> Result;

Texture2D<float4> TopLayer;
Texture2D<float4> BottomLayer;

[numthreads(8, 8, 1)]
void Blend(uint3 id : SV_DispatchThreadID)
{
    if (TopLayer[id.xy].w == 0 && BottomLayer[id.xy].w > 0)
    {
        Result[id.xy] = BottomLayer[id.xy];
    }
    else if (BottomLayer[id.xy].w == 0 && TopLayer[id.xy].w > 0)
    {
        Result[id.xy] = TopLayer[id.xy];
    }
    else if (BottomLayer[id.xy].w == 0 && TopLayer[id.xy].w == 0)
    {
        Result[id.xy] = float4(0, 0, 0, 0);
    }
    else
    {
        float alpha_final = BottomLayer[id.xy].w + TopLayer[id.xy].w - BottomLayer[id.xy].w * TopLayer[id.xy].w;

        float4 tex = 1 - (1 - TopLayer[id.xy]) * (1 - BottomLayer[id.xy]);

        Result[id.xy] = float4(tex.x, tex.y, tex.z, alpha_final);
    }
}

How do I blend images with different alphas properly?

1 Answers

Blending with alpha channels requires weighting with the alpha value.

I hadn’t before thought of how to properly weight in the screen blend case, which is a multiplicative composition. I think it makes sense to do it like a weighted geometric mean: https://en.m.wikipedia.org/wiki/Weighted_geometric_mean): raise the multiplicands to the power of the corresponding weight (the alpha value), then raise the result to the power of the inverse of the sum of weights. Because we want to replicate the standard case when both alphas are 1:

1 - (1-a) (1-b)

which doesn’t have a square root in it, we will divide the sum of alpha values by 2:

1 - [ (1-a)wa (1-b)wb ] 2/(wa+wb)

The output alpha channel itself could be computed in the same way, or could be a simple maximum of the two alpha values. I don’t know what would look better.

Related