Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Can't make bitmap tinted

This thread is locked; no one can reply to it. rss feed Print
Can't make bitmap tinted
Bingocat
Member #15,424
December 2013

I have a freeze gun in my game, and I would like enemies that are frozen to be tinted light blue. I can't get it to work though. Nothing I try makes them blue. Frozen amount is just how many times they were hit by a freezing bullet. So it could be anywhere from 0 to like 20. Here is one of my attempts at getting it to work.

#SelectExpand
1ALLEGRO_BITMAP *buffer2 = al_create_bitmap(128, 128); 2al_set_target_bitmap(buffer2); 3al_draw_rotated_bitmap(buffer, enemies[i].radius, enemies[i].radius, enemies[i].radius, enemies[i].radius, enemies[i].dir, NULL); 4al_set_target_bitmap(al_get_backbuffer(display)); 5al_draw_tinted_bitmap(buffer2, al_map_rgb((int(enemies[i].frozenAmount) * 10), 0, (int(enemies[i].frozenAmount) * 10)), enemies[i].x - enemies[i].radius, enemies[i].y - enemies[i].radius, 0); 6al_destroy_bitmap(buffer); 7al_destroy_bitmap(buffer2);

Edgar Reynaldo
Member #8,592
May 2007
avatar

Like al_draw_bitmap but multiplies all colors in the bitmap with the given color. For example:

Since it multiplies colors, it can only get darker. This is why you can't get a light blue color from using al_draw_tinted_bitmap.

You can either draw a light blue mask over your enemies, or you can pre-draw them light blue and then just draw those instead.

We need a different draw_tinted_bitmap that blends the tint color with the source pixels.

Bingocat
Member #15,424
December 2013

What about al_set_blender()? Is there any way to do it with that?

Edgar Reynaldo
Member #8,592
May 2007
avatar

al_set_blender
al_set_separate_blender

No, neither of those really help you draw something lighter, unless you use additive blending, but that's not the same as tinting. You probably need a shader to do this without having some other kind of intermediate bitmap, such as a mask.

beoran
Member #12,636
March 2011

First of all, I wouldn't use buffers, I'd render directly to the screen using al_draw_tinted_rotated_bitmap.

Secondly,the color mapping is wrong for a bluish tint. Ignoring rotation, I'd go for this:

#SelectExpand
1float frost = (float(enemies[i].frozenAmount)/ 20.0f) * 0.5f; 2al_draw_tinted_bitmap(sprite, al_map_rgba_f(1.0f - frost, 1.0f - frost, 1.0f, 1.0f));

It won't quite become light blue, but it should become blue nevertheless, since the r and g components are lowered progressively.

Bingocat
Member #15,424
December 2013

Oh I had no idea there was an al_draw_tinted_rotated_bitmap(), but again adding the blue color to it just makes the bitmap look darker...

Edgar Reynaldo
Member #8,592
May 2007
avatar

Like I said, it multiplies the two values together and then divides by 255, which is the same as multiplying by a fraction if you use floats, so it just gets darker. You could use additive blending, but that tends to white out large portions of the image.

It should be a fairly simple thing to make a function that creates a mask for your sprite.

Algorithm :
1. Create a mask bitmap the same size as your sprite.
2. Clear the mask bitmap to light blue zero alpha.
3. Draw the alpha layer of the mask bitmap. Look at the src bitmap and wherever it has alpha 0, you want alpha 0 on your mask bitmap (which you can get by leaving that pixel alone). Wherever it has non-zero alpha, you want to set the alpha to the percent they are frozen.
4. When you draw your sprite, draw the mask over the top of it using normal alpha blending (not the same as the default blending, which is pre-multiplied alpha).
5. Draw the sprite and the mask to a buffer to cache resulting bitmaps.

It would be hard to do dynamic freeze levels this way, but it would get you the effect you are looking for, tinting your sprite.

Go to: