Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » [A5] Blender

Credits go to Edgar Reynaldo for helping out!
This thread is locked; no one can reply to it. rss feed Print
[A5] Blender
Hyllis
Member #15,521
February 2014

Hi,

I've a small problem with the use of al_set_blender().
I want to create something like https://www.youtube.com/watch?v=YpQk55bqmUA ; so my first try was with al_draw_tinted_bitmap(), but the effect wasn't really what I expected..
After that, I heard about al_set_blender(), but what I found on it was the same on every website: a copy/paste of the Allegro Wiki.

For exemple, let's say I have:
- my map drawned
- a black box covering the screen (covering the map with shadow)
- a "white" zone/bitmap, to enlight a part of the room

like (in my gameloop ; draw section):

map->DrawMap();

darkarea = al_create_bitmap(config->WIDTH, config->HEIGHT);
al_set_target_bitmap(darkarea);

al_draw_filled_rectangle(0, 0, config->WIDTH, config->HEIGHT, al_map_rgb(0, 0, 0)); // my black screen
al_set_blender(?, ?, ?);
al_draw_bitmap(light, mouse.x - al_get_bitmap_width(light) / 2, mouse.y - al_get_bitmap_height(light) / 2, 0); // my light bitmap (png, transparent at the center, black on the sides)

al_set_target_backbuffer(display);

al_draw_bitmap(darkarea, 0, 0, NULL);
al_destroy_bitmap(darkarea);

In this configuration, what is my "src" and what is my "dst" for the blender?

Sorry for this stupid question ; I search for information on Internet, but everyone tell the same, and since I don't understand it...

Thanks in advance.

Neil Roy
Member #2,229
April 2002
avatar

You should use al_clear_to_color(al_map_rgb(0, 0, 0)) instead of drawing a filled rectangle (which requires you to use the Primitives addon. Also, there's no need to draw everything to a buffer. Just draw to the display which is already buffered. You use al_flip_display() to show it once everything is drawn.

For my own game, I use the following for al_set_blender() which works well...

al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA);

EDIT: Here's all my own display setup code I have in a game I am currently working on...

#SelectExpand
1 if(setting.vsync) al_set_new_display_option(ALLEGRO_VSYNC, setting.vsync, ALLEGRO_SUGGEST); 2 3 if(setting.opengl) al_set_new_display_flags(ALLEGRO_OPENGL); 4 5 al_set_new_bitmap_flags(ALLEGRO_MAG_LINEAR); 6 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA); 7 8 al_set_new_display_option(ALLEGRO_SINGLE_BUFFER, 1, ALLEGRO_REQUIRE); 9 10 if(setting.fullscreen == 1) { // Regular Fullscreen mode (0 = window) 11 if(setting.opengl) al_set_new_display_flags(ALLEGRO_FULLSCREEN | ALLEGRO_OPENGL); 12 else al_set_new_display_flags(ALLEGRO_FULLSCREEN); 13 14 if(setting.frequency) al_set_new_display_refresh_rate(setting.frequency); 15 } 16 else if(setting.fullscreen == 2) { // Fullscreen Window (0 = window) 17 if(setting.opengl) al_set_new_display_flags(ALLEGRO_FULLSCREEN_WINDOW | ALLEGRO_OPENGL); 18 else al_set_new_display_flags(ALLEGRO_FULLSCREEN_WINDOW); 19 20 if(setting.frequency) al_set_new_display_refresh_rate(setting.frequency); 21 } 22 23 setting.screen = al_create_display(WIDTH, HEIGHT); 24 if(!setting.screen) { 25 // do error stuff here 26 }

I have a few settings I load in from a config file that allows me to easily change fullscreen modes, but this supports fullscreen, fullscreen windowed and window, does nice blending with smooth edges etc.

Edgar Reynaldo
Member #8,592
May 2007
avatar

NiteHackr said:

al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA);

That's the same as the default blender which uses pre-multiplied alpha. (Pre-multiplied alpha means you have to multiply the alpha yourself when passing a color, and allegro pre-multiplies the colors in the bitmaps when you load them).

To draw your light / light bitmap use the drawing routines and vary the alpha or draw a white light bitmap with al_draw_tinted_bitmap(bmp , al_map_rgb_f(alpha,alpha,alpha,alpha) , x , y , 0);

If you want an overwrite blender, you need :
al_set_blender(ALLEGRO_ADD , ALLEGRO_ONE , ALLEGRO_ZERO);

Hyllis
Member #15,521
February 2014

Hi, thanks you both for your answers,

My tries with al_draw_tinted_bitmap() failed because I was putting 0 for r, g and b, I was only taking into consideration the alpha ; thanks!

But unfortunately, it doesn't change my problem with the "dark zone" thing (now draw directly on the buffer + al_clear_to_color()) ; I try, with and without it, and with al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA) (default) and al_set_blender(ALLEGRO_ADD , ALLEGRO_ONE , ALLEGRO_ZERO)
=> http://i.imgur.com/P2Ea5B7.png

In both case, the background map disappears, I don't understand why, the blender don't blend the black screen and the transparent light image? apparently no since the transparent become white.

I was using the al_set_blender() in my game loop (in the draw section), but I saw you using it in your display setup at the beginning ; is it important? (I try moving it, but apparently, nothing change)

Thanks in advance ; sorry again for these questions..

Edgar Reynaldo
Member #8,592
May 2007
avatar

You can make a shadow map by overwriting the light areas with zero alpha. Clear a bitmap to black and then 'draw' the 'light' onto it using the overwrite blender I showed you earlier.

And no you can't draw black completely over it and then draw your light and expect it to work properly like in the first example in the image you gave. You have to leave some areas blank so the light or dark doesn't get drawn. That's what the overwrite blender is for.

Hyllis
Member #15,521
February 2014

Oh, I was thinking it could work without it.
Well, I'll read more and try things ; thanks for your help :)

Edgar Reynaldo
Member #8,592
May 2007
avatar

Hyllis
Member #15,521
February 2014

darkarea = al_create_bitmap(config->WIDTH, config->HEIGHT);
al_set_target_bitmap(darkarea);

al_set_blender(ALLEGRO_ADD , ALLEGRO_ONE , ALLEGRO_ZERO);
al_clear_to_color(al_map_rgb(0, 0, 0));
al_draw_bitmap(light, mouse.x - al_get_bitmap_width(light) / 2, mouse.y - al_get_bitmap_height(light) / 2, 0); 
al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA); // <=

al_set_target_backbuffer(display);

al_draw_bitmap(darkarea, 0, 0, NULL);
al_destroy_bitmap(darkarea);

Thanks! My first code + the correct blender mode + go back to the default one at the end (without it, it doesn't work..), and it work as expected.
It could probably be cleaner, but at least, it's a good base for me to start.

Thanks again :).

Go to: