I was testing al_clear_to_color to draw a colored bitmap on top of the back buffer, which was colored, and alpha in the al_map_rgba version doesn't behave like I'd think.
For example if the back buffer was red and the bitmap to draw was green (0 alpha) it would draw yellow as if it was combining them. I just add "_f" to "al_map_rgba" without changing arguments and it behaves as you'd think, with 0 alpha.
Show code for loading and displaying your images...
This code is from allegro 5.1:
al_map_rgba is defined like this:
ALLEGRO_COLOR al_map_rgba( unsigned char r, unsigned char g, unsigned char b, unsigned char a) { ALLEGRO_COLOR color; _AL_MAP_RGBA(color, r, g, b, a); return color; }
With _AL_MAP_RGBA expanding to:
#define _AL_MAP_RGBA(_color, _r, _g, _b, _a) \ do { \ (_color).r = _al_u8_to_float[_r]; \ (_color).g = _al_u8_to_float[_g]; \ (_color).b = _al_u8_to_float[_b]; \ (_color).a = _al_u8_to_float[_a]; \ } while (0)
_al_u8_to_float is an array of 256 floats and is filled in _al_init_pixels like this:
int i; for (i = 0; i < 256; i++) _al_u8_to_float[i] = i / 255.0; }
The first entry in it should be 0. So it will put 0.0f as the .a component of the color struct, unless something fishy is going on.
al_map_rgba_f is way simpler, it just sets the values:
ALLEGRO_COLOR al_map_rgba_f(float r, float g, float b, float a) { ALLEGRO_COLOR color; color.r = r; color.g = g; color.b = b; color.a = a; return color; }
So unless there's some weird memory corruption, those two calls should have the same effect.
So unless there's some weird memory corruption, those two calls should have the same effect.
Or you didn't initialize Allegro.
draw a colored bitmap on top of the back buffer
I don't think you can have a backbuffer if you don't initialize allegro. You will indeed run into the problem if you call al_map_rgba before initializing though.
I just add "_f" to "al_map_rgba" without changing arguments and it behaves as you'd think, with 0 alpha.
Something important to note is that al_map_rgba_f takes values from 0.0 to 1.0, and al_map_rgba takes values from 0-255.
If the argument given is 0, that makes no difference.
Yes, I know that, thanks. I was pointing out that they take different parameters because it sounded like he was not aware of that.
Allegro uses pre multiplied alpha blending by default, for various reasons.
// pre multiplied alpha blender, this is the default
al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA)
ALLEGRO_ADD
r = dr * dst + sr * src
g = dg * dst + sg * src
b = db * dst + sb * src
a = da * dst + sa * src
With src of (0,255,0,0) and dst of (1,0,0,?)
r = dr*(1-sa) + sr*1.0
g = dg*(1-sa) + sg*1.0
b = db*(1-sa) + sb*1.0
r = 1.0*(1-0) + 0*1 = 1
g = 0*(1-0) + 1*1 = 1
b = 0*(1-0) + 0*1 = 0
Which is yellow, and is exactly what you were getting.
If you are using non-pre-multiplied alpha, you could use
al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA)
Also, why are you trying to draw a fully transparent bitmap anyway? What's the point?
Also, why are you trying to draw a fully transparent bitmap anyway? What's the point?
I bet he was trying to find out why partial transparency didn't work right either, like taking extreme cases. I do stuff like that all the time.
I should have checked in earlier, I've since removed the code.
What I was doing exactly was testing al_clear_to_color with al_set_clipping_rectangle to see if I could "hide" parts of a fully opaque bitmap.
When I first read the manual entry for al_map_rgba_f I thought it meant that the alpha is 0-1 and the others were still 0-255 :/ Either way it was the al_map_rgba version that was using the alpha strangely (the color values themselves seemed to affect the alpha -- 0, 0, 0, 0 was not visibly the same as 255, 0, 0, 0)
Edit: Add this code to any program after rendering Buffer before copying it to the back buffer:
al_set_clipping_rectangle(5, 5, 20, 20); // target should be your buffer and rectangle can be anything in its bounds al_clear_to_color(al_map_rgba(255, 0, 0, 0)); al_set_clipping_rectangle(0, 0, al_get_bitmap_width(Buffer), al_get_bitmap_height(Buffer));
That shows up as red to me, but if I change the al_map_rgba to al_map_rgba_f it works as I'd think it'd work, with 0 alpha meaning 0 alpha (aside from the fact that the color of a translucent alpha would be incorrect due to 255 not being between 0-1, but my point is alpha is working)
(the color values themselves seemed to affect the alpha -- 0, 0, 0, 0 was not visibly the same as 255, 0, 0, 0)
That's because the default blending mode use pre-multiplied alpha which means the dst in the blending formula will always be 1 - source alpha. If sa is 0, the dest is added at full intensity. If sa is 1, the destination is ignored. Since you're using ALLEGRO_ADD in the default blender, and ALLEGRO_ONE for src, the source will always be added to the resulting color, even with a source alpha of 0.
ALLEGRO_ADD
r = dr * dst + sr * src
g = dg * dst + sg * src
b = db * dst + sb * src
a = da * dst + sa * src
where dst is (1-sa) and src is 1.
To use the default blender with a bitmap that you clear to a certain color, the color needs to be mulitiplied by the alpha first :
al_clear_to_color(al_map_rgba((r*a)/255) , (g*a)/255 , (b*a)/255 , a));
Then you could draw that bitmap normally with the default blender.
Edit
That shows up as red to me, but if I change the al_map_rgba to al_map_rgba_f it works as I'd think it'd work, with 0 alpha meaning 0 alpha (aside from the fact that the color of a translucent alpha would be incorrect due to 255 not being between 0-1, but my point is alpha is working)
That's probably just a quirk of the fact that 255.0f is not between 0.0 and 1.0.
Thanks for the info