Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Lighting and Allegro 5

This thread is locked; no one can reply to it. rss feed Print
 1   2 
Lighting and Allegro 5
Myrdos
Member #1,772
December 2001

I was looking at the Allegro 5 examples, some of which are very sexy, and I thought it would be cool to add a 'headlights' effect to my game like so:

{"name":"one_headlight.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/3\/4\/343d78b66f23dbb6f3ccf7e52c2c93cd.png","w":641,"h":364,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/3\/4\/343d78b66f23dbb6f3ccf7e52c2c93cd"}one_headlight.png

Can it be done with Allegro, or would it require OpenGL? I'd like the light to be as realistic as possible.

Also, would it be possible to use Allegro for the drawing, and OpenGL only for the lighting? Or, once you use OpenGL, do you have to use it for everything?

__________________________________________________

Trent Gamblin
Member #261
April 2000
avatar

If you just want to do what's in the screenshot, you can do that easily with primitives and blending. I don't know how realistic you want to go though... you can mix opengl and allegro calls no problem as long as you don't mess up opengl state and you know how allegro is affecting opengl state as well.

Myrdos
Member #1,772
December 2001

I don't know how realistic you want to go though...

Well, I'd like to have the light fade with distance. The only blending function I see is "al_set_blender". Would I have to set the blending function for every pixel in software, depending on how far the pixel is from light source(s)?

Quote:

as long as you don't mess up opengl state and you know how allegro is affecting opengl state as well

Sounds tricky, but doable.

__________________________________________________

Trent Gamblin
Member #261
April 2000
avatar

Fading with distance shouldn't be a big problem if the light is a constant shape. You could have a bitmap that is a white triangle/trapezoid that fade from full alpha (or whatever you want) down to no alpha to the end. Then draw that with additive blending, maybe draw it more than once for a better effect. al_set_blender is all you need. You can achieve an additive blender with al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ONE).

Myrdos
Member #1,772
December 2001

You could have a bitmap that is a white triangle/trapezoid that fade from full alpha (or whatever you want) down to no alpha to the end.

I like that! I think it might even be possible to add shadowing by blitting the terrain in front of the car onto the 'light triangle', such that the terrain areas have zero alpha.

Hmm... I could even pre-process my terrain so that the edges of the terrain are illuminated, but the interior remains dark.

{"name":"another_headlight.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/f\/a\/fa2c531a2279ea9733927c783005c6cf.png","w":530,"h":322,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/f\/a\/fa2c531a2279ea9733927c783005c6cf"}another_headlight.png

[EDIT] Oops, forgot to ask: Why would applying the light triangle multiple times improve the results?

__________________________________________________

Trent Gamblin
Member #261
April 2000
avatar

The only reason it might help is to make it brighter. You could also draw it with less or more alpha, even modifying them in real time so that it looks like it's "glowing". I don't recall what sort of transparency you'll see if you have say full alpha and draw additively... that's why I suggested drawing more than once. If it's 100% white at that point then drawing again wouldn't help but if was 50% you could get a brighter light by drawing more than once.

Myrdos
Member #1,772
December 2001

I guess I'll experiment with it and see what it looks like.

Thanks for all the help!

[EDIT] Hmmm... no way to give cookies. :-/

__________________________________________________

Trent Gamblin
Member #261
April 2000
avatar

That's ok, I need to watch my weight anyway :P.

Matthew Leverton
Supreme Loser
January 1999
avatar

It shouldn't brighten the area behind the hill as dramatically as your screenshot shows, although it may not really matter much in the context of the game.

Trent Gamblin
Member #261
April 2000
avatar

See the last image in the thread. He plans to draw the "scenery" back over top of the light except for an edge which I think will work ok.

Myrdos
Member #1,772
December 2001

It shouldn't brighten the area behind the hill as dramatically as your screenshot shows, although it may not really matter much in the context of the game.

I know, if you can think of a way to add shadows I'd be interested...

My attempt at a light so far has been of limited success:

{"name":"light1.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/5\/f\/5f1f05301f61f01d14e87401ebf8faf2.png","w":648,"h":485,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/5\/f\/5f1f05301f61f01d14e87401ebf8faf2"}light1.png

It's creating a kind of 'fog' effect, rather than illuminating anything. I'm drawing it like so:

         al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ONE);
         al_draw_scaled_bitmap(spotlight, 0, 0,
                               al_get_bitmap_width(spotlight), al_get_bitmap_height(spotlight),
                               50, 60,
                               al_get_bitmap_width(spotlight) * 2, al_get_bitmap_height(spotlight) * 2,
                               0);

The spotlight bitmap is made of white pixels with varying amounts of alpha. Any ideas on how to improve this?

__________________________________________________

Trent Gamblin
Member #261
April 2000
avatar

What would really improve it is if you can somehow get the background image into a trapezoid and draw that with additive blending... I'm not sure how you'd do that without shaders except using the stencil buffer. Both are kind of "exotic". To do it with the stencil buffer you'd have a stencil the shape of the trapezoid and a translucent->black version of the trapezoid. You would draw from the display (or if that turns out to be too slow, you could have an intermediate buffer) to a bitmap with the stencil on so only the trapezoid gets drawn (the rest would be pure alpha or black) and then draw the black/alpha bitmap over that before drawing it with additive blending.

EDIT:
Scratch that, you could use have extra black in the black/alpha image wherever the trapezoid doesn't touch. So no need for stencil or anything exotic.

gnolam
Member #2,030
March 2002
avatar

Hint: Lightmaps don't actually lighten pixels, they darken them.

--
Move to the Democratic People's Republic of Vivendi Universal (formerly known as Sweden) - officially democracy- and privacy-free since 2008-06-18!

Myrdos
Member #1,772
December 2001

gnolam said:

Hint: Lightmaps don't actually lighten pixels, they darken them.

So... I should selectively darken the terrain, except where the light is. Makes sense...

Scratch that, you could use have extra black in the black/alpha image wherever the trapezoid doesn't touch. So no need for stencil or anything exotic.

I not sure if I completely follow you here, but is that similar to what I have now? The parts of the spotlight that aren't 'light' are black with 0 alpha.

Let me run this past you:

1) I fill the back buffer with black.

2) I draw my terrain to a bitmap, using 80% transparency.

3) I draw the light to the bitmap, but use blending such that the alpha value of the light pixels are added to the terrain, but not the colors.

4) I blit the result to the back buffer

Is that type of blending possible?

__________________________________________________

Trent Gamblin
Member #261
April 2000
avatar

{"name":"604620","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/8\/4\/842ef10cbe84998c0a06ce138a69313f.png","w":646,"h":430,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/8\/4\/842ef10cbe84998c0a06ce138a69313f"}604620

That's what I got with what I said above. Easier for me to post code than to describe it. The image I used is also attached.

#SelectExpand
1#include <allegro5/allegro.h> 2#include <allegro5/allegro_image.h> 3 4int main(void) 5{ 6 al_init(); 7 al_init_image_addon(); 8 9 ALLEGRO_DISPLAY *display = al_create_display(640, 400); 10 al_clear_to_color(al_map_rgb_f(0, 0, 0)); 11 12 ALLEGRO_BITMAP *allegro = al_load_bitmap("allegro.pcx"); 13 ALLEGRO_BITMAP *trap = al_load_bitmap("trap.png"); 14 ALLEGRO_BITMAP *buf = al_create_bitmap(640, 400); 15 ALLEGRO_BITMAP *tmp = al_create_bitmap(320, 200); 16 17 al_set_target_bitmap(buf); 18 al_clear_to_color(al_map_rgba_f(0, 0, 0, 0)); 19 al_draw_tinted_bitmap(allegro, al_map_rgba_f(0.2, 0.2, 0.2, 1.0), 0, 0, 0); 20 al_draw_tinted_bitmap(allegro, al_map_rgba_f(0.2, 0.2, 0.2, 1.0), 320, 0, 0); 21 al_draw_tinted_bitmap(allegro, al_map_rgba_f(0.2, 0.2, 0.2, 1.0), 0, 200, 0); 22 al_draw_tinted_bitmap(allegro, al_map_rgba_f(0.2, 0.2, 0.2, 1.0), 320, 200, 0); 23 24 al_set_target_bitmap(tmp); 25 al_clear_to_color(al_map_rgba_f(0, 0, 0, 0)); 26 al_draw_bitmap_region(buf, 160, 100, 320, 200, 0, 0, 0); 27 al_draw_bitmap(trap, 0, 0, 0); 28 29 al_set_target_bitmap(buf); 30 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ONE); 31 al_draw_bitmap(tmp, 160, 100, 0); 32 al_draw_bitmap(tmp, 160, 100, 0); 33 34 al_set_target_backbuffer(display); 35 al_draw_bitmap(buf, 0, 0, 0); 36 al_flip_display(); 37 38 al_rest(10); 39 40 return 0; 41}

EDIT: I'm going to explain what the code does so I can use it as a blog post or wiki article.

The key thing happening here is you have a completely rendered scene, except for the light(s), and you can quickly draw parts of that scene to a different destination bitmap. You need an image defining the shape and cutoff of the light as well.

In this example, our "scene" is just the allegro.pcx image drawn 4 times to fit a 640x400 window, at 20% brightness. That's what the first lines of code after loading bitmaps does.

After that's done, the area that will be lit is drawn to a "temporary"/work bitmap. Then the light-shape-definition bitmap is drawn over top of that, which gives us a bitmap with the colors we want (color directly from the scene) and the shape (due to drawing the trapezoid over top).

The last thing that needs to be done is to set the target back to your scene and draw the "temporary" image we made back over top of the scene at the same point we copied from earlier. We use additive blending to draw it, and draw it as many times as needed to give the desired brightness.

Mark Oates
Member #1,146
March 2001
avatar

I'm confused.

1) draw scene
2) draw shadow layer with subtractive blender
3) problem???

--
Visit CLUBCATT.com for cat shirts, cat mugs, puzzles, art and more <-- coupon code ALLEGRO4LIFE at checkout and get $3 off any order of 3 or more items!

AllegroFlareAllegroFlare DocsAllegroFlare GitHub

Trent Gamblin
Member #261
April 2000
avatar

1) subtractive blending is not supported on all chips
2) you still have to do basically the same thing anyway. What am I missing?

Mark Oates
Member #1,146
March 2001
avatar

The multiply blender would work, but it doesn't appear that that's available until 5.1. Until then, I would then do it as thus:

al_draw_bitmap(af_get_image("scene.png"), 0, 0, NULL); // < draw scene

af_push_state(ALLEGRO_STATE_BLENDER); // < obvious what this does, I guess
al_set_blender(ALLEGRO_DEST_MINUS_SRC, ALLEGRO_ONE, ALLEGRO_ONE);  // < makeshift subtractive blender
al_draw_bitmap(shadow_layer, 0, 0, NULL); // < draw scene
af_pop_state();

The work-around being that you'll have to draw your shadow layer inverted. Black is white and white is black - because the blender is subtracting more when the value is white.

scene:
{"name":"604625","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/0\/8\/08948338172946a48c2856efb03cfa55.png","w":962,"h":723,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/0\/8\/08948338172946a48c2856efb03cfa55"}604625
shadows (drawn inverted):
{"name":"604628","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/9\/0\/90812f9929357cb5da1cddf831d87512.png","w":962,"h":723,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/9\/0\/90812f9929357cb5da1cddf831d87512"}604628
composite (drawn with ALLEGRO_DEST_MINUS_SRC, ALLEGRO_ONE, ALLEGRO_ONE):
{"name":"604629","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/d\/5\/d5a6ac624bfa87c0c4c1043dc8dec8ec.png","w":962,"h":723,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/d\/5\/d5a6ac624bfa87c0c4c1043dc8dec8ec"}604629
There's some really sexy color curves on the low-level shadows. :)

[edit] er... is ALLEGRO_DEST_MINUS_SRC the part that's not supported on all chips? Which chips are affected?

--
Visit CLUBCATT.com for cat shirts, cat mugs, puzzles, art and more <-- coupon code ALLEGRO4LIFE at checkout and get $3 off any order of 3 or more items!

AllegroFlareAllegroFlare DocsAllegroFlare GitHub

Elias
Member #358
May 2000

Well, in DirectX you have to query a flag and in OpenGL it's an extension you check for. So there at least were chips at one point which did not support it. I'd say all GPUs with shader support support it as it's now just a matter of shipping the right shader in the drivers for emulating the old fixed pipeline blending.

--
"Either help out or stop whining" - Evert

Trent Gamblin
Member #261
April 2000
avatar

Ok, now how do you move the light? You have to recreate the shadow layer each time it moves, and it will be constantly moving, so like I said, basically the same thing I posted but inverted, or am I still missing something?

Mark Oates
Member #1,146
March 2001
avatar

Ok, now how do you move the light?

You just draw the light in a different place.

Quote:

basically the same thing I posted but inverted

I guess mine has less code?... I dunno. Right now I'm brain-mush confus from trying to learn shaders. :P

--
Visit CLUBCATT.com for cat shirts, cat mugs, puzzles, art and more <-- coupon code ALLEGRO4LIFE at checkout and get $3 off any order of 3 or more items!

AllegroFlareAllegroFlare DocsAllegroFlare GitHub

Trent Gamblin
Member #261
April 2000
avatar

You can't just draw it in a different place. In your example is has to be drawn over the whole scene and thus fill the whole screen so moving it would make gaps in places. This is for a car. Imagine the car driving along then going up a hill. Now imagine there are 5 cars all with headlights on.

Myrdos
Member #1,772
December 2001

Trent: I've got your example working. \o/

I've got some code that draws a spotlight onto a bitmap, with a variable angle, beam length, brightness and aperture size. Do you think it would be worth submitting it to the Allegro dev team? It requires math.h.

__________________________________________________

Trent Gamblin
Member #261
April 2000
avatar

I don't personally think it fits in Allegro... seems too high level. You could post it on the wiki. I'm sure that would be useful for someone.

Mark Oates
Member #1,146
March 2001
avatar

You can't just draw it in a different place. In your example is has to be drawn over the whole scene and thus fill the whole screen so moving it would make gaps in places.

The shadow layer is a second buffer, just like the the display backbuffer. In the normal backbuffer you draw your scene, the sprites, trees, enemies and whatnot. As you draw their sprites (or in a separate process), you draw their shadows to that "shadowbuffer."

Here's your light triangle (thumbnail doesn't render correctly because it has alpha:
{"name":"604636","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/e\/6\/e624155cc668c4b6c3d2e6674ed83fa7.png","w":950,"h":605,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/e\/6\/e624155cc668c4b6c3d2e6674ed83fa7"}604636

Once all that's done you put the two together.

This is basically how I would do it, except I would try to see how many more features I could work in (except I would probably get frustrated and quit after I couldn't get them all in.)

  1. cast rays and draw long shadows

  2. desaturate and blue-tint the shadows.

  3. introduce surface hilights and shine onto some sprites

  4. blur increases from their light sources

  5. overall amplify the light blending that's closest to the light source.

  6. put in a little mini lens-flair

Most of these require shaders. The end might look something like this (photoshop):

{"name":"604637","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/2\/5\/25aca9c4603800a22883474df0ba7228.png","w":958,"h":660,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/2\/5\/25aca9c4603800a22883474df0ba7228"}604637

--
Visit CLUBCATT.com for cat shirts, cat mugs, puzzles, art and more <-- coupon code ALLEGRO4LIFE at checkout and get $3 off any order of 3 or more items!

AllegroFlareAllegroFlare DocsAllegroFlare GitHub

 1   2 


Go to: