al_map_rgba vs. al_map_rgba_f
Felix-The-Ghost

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. :-/

Edgar Reynaldo

Show code for loading and displaying your images...

J-Gamer

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.

SiegeLord
J-Gamer said:

So unless there's some weird memory corruption, those two calls should have the same effect.

Or you didn't initialize Allegro.

J-Gamer

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.

Edgar Reynaldo

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.

J-Gamer

If the argument given is 0, that makes no difference.

Edgar Reynaldo

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.

Quote:

// 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.

Quote:

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?

Arthur Kalliokoski

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.

Felix-The-Ghost

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)

Edgar Reynaldo

(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.

Quote:

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

Quote:

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.

Felix-The-Ghost

Thanks for the info :)

Thread #614684. Printed from Allegro.cc