Hello I'm drawing tinted bitmaps and work with the blending modes.
I understand that tinting multiplies the colors and the alpha of bitmaps before drawing them.
But when I use blending mode ADD / ALPHA / INVERSE ALPHA I don't understand exactly what happens. I assume the rgba of the source bitmap are multiplied with the source's alpha and the destination bitmap's rgba with the inverse alpha of the source bitmap.
To me it seems that the multiplying with alpha/inverse alpha only lightens or darkens the colors of the bitmap, but not making them less or more solid or visible. Maybe anyone can explain it in a good way?
al_draw_tinted_bitmap will multiply each pixel of the bitmap you are drawing with the tint color. So for example if your tint color is 0/0/0/0 you will not be drawing anything (your bitmap turns into a completely transparent rectangle).
If your tint color is 1/1/1/1 you draw the exact same bitmap you already had, same as if calling al_draw_bitmap. (Everything is multiplied by 1 so stays the same).
If you use 0.5/0.5/0.5/0.5 then each pixel gets half as transparent as it was. For example a solid red pixel (1/0/0/1) in your bitmap will now be drawn as a 50% transparent pixel (0.5/0/0/0.5).
Does that help?
Blending itself is completely separate and happens after tinting the source bitmap. With ADD / ALPHA / INVERSE ALPHA you basically do something like this for each pixel:
result = pixel_already_there * INVERSE ALPHA + pixel_from_bitmap * ALPHA
So it's more like two multiplications and one addition, not just a multiplication.
Okay, the problem is that when blending I don't understand why the r, g and b components of the pixels are multiplied with the alpha/inverse alpha components, too, because I think that changes their color/tone only, and not their solidity/visibility. So to me it looks like that multiplying the color with the alpha/inverse alpha would Change their intensity or color tone which I don't want, that's what tinting is for. So I wonder why it does not suffice to just tint with 1, 1, 1, 0.5 to let the color unchanged and change visibility of the pixel to 0.5 and the blending mode (ADD, ALPHA, INVERSE ALPHA) then does the change of the visibility. Why are in that blending mode the RGB multiplied by alpha/inverse alpha, too? That changes the color I think.
The following page explains this well https://en.wikipedia.org/wiki/Alpha_compositing
Tinting is done before blending, as Elias pointed out.
Tinting is done with the vertex color of the triangle(s). It's essentially free, and allows you to 'tint' the vertex. It multiplies each color in the texel by the amortized distance from the vertex and the color of the vertices after they've been weighted.
Tinting :
Weighted Vertex color 0.5,0.5,0.5,0.5 (using premultiplied alpha here)
Texel color 0.8,0.6,0.4,1.0 (source texel)
Result 0.4,0.3,0.2,1.0
Note the color changed, because when you apply alpha to a color, it can only make it lighter (less to contribute to the final color). That's why it's being pre-multiplied here.
Closely related, but slightly more involved is the blending process.
This uses an operator, and two factors to determine the blended pixel color.
Now if you're drawing a translucent image, and you want it to draw the alpha correctly, you use pre-multiplied alpha blending.
al_set_blender(ALLEGRO_ADD , ALLEGRO_INVERSE_ALPHA , ALLEGRO_ALPHA);
This will give you SRC*INVERSE_ALPHA + DEST*ALPHA for the blending mode.
Example :
Source texel color 0.0 , 0.7 , 0.0 , 0.7 (PM alpha again) INVERSE_ALPHA * 0.3 , 0.3 , 0.3 , XXX --------------------------------------------- 0.0 , 0.21, 0.0 , XXX + Destination texel color 1.0 , 0.0 , 1.0 , 1.0 ALPHA * 0.7 , 0.7 , 0.7 , XXX --------------------------------------------- 0.7 , 0.0 , 0.7 , XXX --------------------------------------------- 0.7 , 0.21, 0.7 , XXX
So you can see it overlays a translucent green pixel over a hot pink pixel and ends up slightly desaturated due to the addition of green.
Why are in that blending mode the RGB multiplied by alpha/inverse alpha, too?
Because alpha is pre-multiplied. You can actually make Allegro not use pre-multiplied alpha when loading bitmaps, in which case the above would keep the color. However look at the ex_premulalpha example for a reason why that's a bad idea (basically linear rgba interpolation breaks.)