![]() |
|
Colors behaving differently than expected |
Eric Johnson
Member #14,841
January 2013
![]() |
I made a mock-up of three circles overlapping one another in GIMP, each with its opacity set to 50%. See the first attachment for the results. Then I drew the same three circles in Allegro 5 using al_draw_filled_circle(), each with its alpha set to 128. However, the Allegro 5 results were different than what I got from GIMP. See the second attachment. Here's my code: 1#include <allegro5/allegro.h>
2#include <allegro5/allegro_primitives.h>
3
4int main(void) {
5
6 al_init();
7
8 al_init_primitives_addon();
9
10 ALLEGRO_DISPLAY *display = al_create_display(256, 256);
11
12 al_clear_to_color(al_map_rgb(255, 255, 255));
13
14 al_draw_filled_circle(80, 144, 64, al_map_rgba(255, 255, 0, 128));
15 al_draw_filled_circle(144, 80, 64, al_map_rgba(255, 0, 0, 128));
16 al_draw_filled_circle(144, 144, 64, al_map_rgba(0, 0, 255, 128));
17
18 al_flip_display();
19
20 al_rest(5);
21
22 al_destroy_display(display);
23
24 return 0;
25}
So what's the deal? I expected Allegro to generate the same result as GIMP, but it's different. Why is this?
|
Erin Maus
Member #7,537
July 2006
![]() |
Allegro uses pre-multiplied alpha by default. You'd need to multiply the color channels by the fractional alpha (e.g., 0.5). Otherwise, you get an additive effect. http://liballeg.org/a5docs/trunk/graphics.html#al_premul_rgba_f http://liballeg.org/a5docs/trunk/graphics.html#al_set_blender --- |
Chris Katko
Member #1,881
January 2002
![]() |
I would love if Allegro had a tutorial / explaination of the reasoning for the different blending modes, and why pre-multiplied is the default. That's something I've never understood. -----sig: |
Eric Johnson
Member #14,841
January 2013
![]() |
Thanks for linking to the docs, Aaron. I'm with Chris on this one; I'm curious to know the reason for using pre-multiplied alpha by default as well.
|
Elias
Member #358
May 2000
|
Just looking at ex_premulalpha should be enough reasoning - without pre-multiplied alpha it leads to incorrect results, with pre-multiplied alpha it leads to the correct results. The explanation is simple. When OpenGL interpolates it does linear interpolation on all channels. So lets say you draw a texture where one pixel is opaque red (red = 1, green = 0, blue = 0, alpha = 1). And the pixel next to it is completely transparent black (red = 0, green = 0, blue = 0, alpha = 0). Now you scale this up enough that OpenGL has to interpolate a pixel between those two - it will therefore be: red = (1 + 0) / 2 = 0.5 So far, there is no difference between normal and pre-multipled alpha. Now OpenGL draws that pixel, lets say on a completely black background (red_back = 0, green_back = 0, blue_back = 0). The result is: result_red = red_back * (1 - alpha) + red * alpha = 0 + 0.5 * 0.5 = 0.25 We drew a pixel that is 25% red instead of a pixel that clearly should be 50% red, as it is exactly between the completely red and the completely black one! So, just like you can see in ex_premul_alpha, it appears wrong. What if we use pre-multiplied alpha? result_red = red_back * (1 - alpha) + red = 0 + 0.5 = 0.5 Now we get the correct 50% red between the full red and the full black pixel. In a way the problem is just that with not pre-multiplied alpha there is very many ways to specify transparent colors, e.g. 0/0/0/0 and 1/1/1/0 are both the exact same 100% transparent color. But one will darken everything when interpolating to it and the other will interpolate everything to white - and there is no way to simply interpolate towards transparency. -- |
amarillion
Member #940
January 2001
![]() |
I have to agree with Chris - this is the bit where I had most difficulties porting allegro 4 games to allegro 5. They way blending works is different and hard (at least for me) to wrap my head around. -- |
|