Realtime Lighting

My engine is perfect so far, and I want to take it another step up.

I was wondering what anyone knows about lighting, be it approaches to doing so,
useful links on information, etc. Things that I hope don't require a mastery of math that scares most people.

Like if you're walking round in an RPG, or something, to enter a room, turn on a light or be in a cae and walk by a torch etc and get at least the basic effects.

I have some things in mind for simple stuff, but I'd really like more input on such things if anyone has some.

Jonatan Hedborg

2d - Top down/isometric? 3d?


it's all 2D. I'm not good enough at math to do 3D, unfortunately.
2d Sidescroller, RPG, etc. I think the same principle would work for any 2D type?

Jonatan Hedborg

mostly, yes. There are a few different ways to do it. You can render a "light blob" (gradient in the shape of your light, in the color of your light) with multiplicative blending or additive blending. Or, you could render tiles with gouraud shading (for 2d top-down). In any event, you will probably need to use fblend or openlayer if you want decent performance.


yeah thats what I use. I've done some amazing things with it. OpenLayer's really nice. ^^ yes, yes, I see.....I could make different shapes, and just size and place them appropriately.

How would I do it for animated torchlight, so that the flickering flame has effect on the lighting as well? perhaps just use the animation itself (expanded to light distance size) as the light source itself? hmm...that might not be right, just thinking off the top of my head here. ^^;;;


perhaps just use the animation itself (expanded to light distance size) as the light source itself?

Use a different 'light blob' for each flame animation frame?


yeah, that might work! ^^

Do they have to be made at run time, or can I have preset shapes in a datafile as well??

I have another idea....

If one was to enter a dark house, isn't it wierd if turing on the light makes only this round light source and the rest of the room stays dark. I was thinking of doing
a calculation based on the number of lights in the room and I would sort of 'flood' the room with it. like the global darkness added to the entire room would light up by a very slight amount with each light turned on until the whole room is lit. this would of course be calculated as well based on how large/bright etc the light source is. I was assuming that you dont see the light image unless something is in the way to be lit but that didnt work. so as the room floods with light, the lights themselves darken, giving the effect of what you'd see in real life, how the total light of the room would affect how much you can see from the source.

does that sound correct? I'm still only guessing a bit here. I'm trying to find ways of making it a bit more lifelike. maybe I need to do shadows as well??


The game "The Project 2" uses a general light level for each level (it currently does not change during play, but it could), somewhere between full dark and full light.

At the beginning of each redraw, it blits a solid rectangle of this light on a screen-sized bitmap.
Then, it blits on this layer the highlights from lamps, gunfire, and the player's torch (level 5)
The draw mode is additive or multiply, I didn't check the formula.

Then this layer is blit on the actual game screen, again in additive/multiply mode.


Shadows are often not computed together with lights, because generally you want lights 'over' sprites and background, and shadows between the sprites and background.


Ahh, ok. well I can give all these things a try.

How would I blit in Multiply mode? Openlayer seems not to have such an option in it's blenders...


I remember I made a thread about it a long time ago. You can search for it, if you want. Here's a game I never finished, which is using dynamic shadows and lighting:


heheh, pretty cool! I had a good ol' time making things blow up with that G key.
In fact I did it SO much it crashed. oops.... ^^;;;

I looked at the shadow code. I really like how the light from the explosion thingie goes around walls. thats the part I didn't know how to do. I have such a hard time understanding other people's code tho. x.x Mainly cuz I usually work beast in my head. I just come up with these designs, and I know just what I'm doing, but when I have to read stuff someone else wrote and really think about it alot, it's a little harder. I kinda got lost at the math stuff. I really suck at that. Were ya creating the light poly's in realtime? cuz I was just using preset shapes in a datafile because I'm not very good at it otherwise yet.
It would probably make more sene to me but theres references to stuff I don't see
like what BlockedTile() is doing, etc. whats really WIERD, is that even if I don't
know how to do it from code I see, I'll have a much easier time trying to design it my own way. basically, isnt what this doing is checking for light that touches the tiles and removing what passes over them? sorry, I'm probably being a little slow to catch on here. x.x

Fladimir da Gorf

There's no multiply mode, but subtractive mode comes close. Also, Blenders::Set( GL_ZERO, GL_ONE_MINUS_SRC_COLOR ) might work as a multiplicative blender...


Ok, I'll give that a try! ^^

Btw, how does multiply mode work/is used for as opposed to using additive?
I've never used such things before. This is my first time working with blending on
a scale like this.

Fladimir da Gorf

In multiply mode, for each color component of every pixel: result = (1.0 - srcComp) * dstComp;
Additive mode: result = srcComp + dstComp;

(src is the image you're rendering and dst is the surface (screen))

The first parameter of Blenders::Set is the src factor and the second parameter is the dest factor. Now Blenders::Set(GL_ZERO, GL_ONE_MINUS_SRC_COLOR) should be: result = 0 * srcComp + (1.0 - srcComp) * dstComp; which is the same as the multiplicative blender.

Did that make any sense? :)

By the way, you asked if OpenLayer can do page flipping. In fact it can't do anything else since everything happens in the video card :) (double buffering in video card is called page flipping)


Ahh, I think I get it, yes. ^^
But what I really meant was what kind of effect is it good for?
Like why would someone want to use that for lights over additive?

Oh yeah! I kinda thought that myself, that it was already doing what it needed to.

Wow, I really thank everyone for the input so far! I'll give people a look at my....very engine when I'm ready with it. :D

Fladimir da Gorf

Multiply blender is used to darken the areas that don't have much light. Additive blending, on the other hand, is used to lit areas that have an excessive amount of light. Which one you want to use depends on what you want to get.

Jonatan Hedborg

the "perfect" solution would be to render all lights using additive blending to a "buffer" (not sure how this would be done, if at all possible, in openlayer), which you then render onto the screen in multiply mode. This way you would create all your sprites as if they were 100% lit and they would come out fine (anything not covered by a light would be suitably darker).

If you use just additive on the other hand, everything will be very "washed out" and there will be no "unlit" areas - only "lit" and "superbright" :) One option would be to create sprites at, say, 50% illumination. It might be a suitable middle ground if it's not possible to do the first option, even though you lose some details (i think).

Fladimir da Gorf

Using Canvas or copying the contents of the back buffer to a Bitmap would work, but would also have a slight performance penalty.


That sounds very interesting! :D

Hmm...well, actually, what I was going to do was something very similar, but
use a sort of central light source. for example, if its daytime outside, the
buffer that darkens everything would be set to normal, and the higher the main light level, the less visible any lights are. If there was a lamp post, it would barely generate any visible light at all or maybe none depending on how bright it is outside. Indoors, the more lights turn on, the more the indoor 'main' light source goes up and the more the lights become less visible. each light would cause a sort of flooding effect, spreading into the room. I thought I'd work on such calculations and see what kind of effects I can get. ^^
That Multiply blender could be of real use for such when you need things to get darker.

For some odd reason, using more than one Canvas always renders garbage to the screen for me. Do I set Canvas to a buffer bitmap, do my blitting and then refresh that one? am I doing it wrong?
Do I really need to use a Buffer? So far, my engine has just done all it's drawing
to the main canvas, and theres no performance problems no matter what I try and throw at it. And I literally had FMV playing as background, a pretty realistic thunderstorm going on in front of that, the tiles, character, regular game gfx, lights etc and it runs smoothly on a GeForce 4 64MB and up. (I tried GF3 up to a GF7800 and RadeonX1600, the GF3 only had any problems on a lower end cpu if an FMV was playing at the same time as main gameplay)
I just love hardware acceleration.....Push those video cards for all they're worth!

Jonatan Hedborg

I took the liberty of trying this out myself (yes, I am aware there is no error checking/handling).

1#include <OpenLayer.hpp>
3using namespace ol;
5int main() {
6 Setup::SetupProgram();
7 Setup::SetupScreen(800,600,false);
9 Bitmap lightmap(800, 600);
10 Bitmap image("test.png");
12 FpsCounter::Start(1.0f);
13 while(!key[KEY_ESC]) {
14 float delta = FpsCounter::NewFrameStarted();
16 //Logic code here
19 //Draw lights
20 Canvas::SetTo(lightmap);
21 Canvas::Fill(Rgba::BLACK);
22 Blenders::Set(ADDITIVE_BLENDER);
23 Circle(Vec2D(mouse_x,mouse_y),200).Draw(Rgba(200,160,50), Rgba::INVISIBLE);
24 Circle(Vec2D(800-mouse_x,600-mouse_y),200).Draw(Rgba(20,50,240), Rgba::INVISIBLE);
25 Circle(Vec2D(600,200),200).Draw(Rgba(128,128,128), Rgba::INVISIBLE);
26 Canvas::Refresh();
28 //Draw scene
29 Canvas::SetTo(SCREEN_BACKBUF);
30 Blenders::Set(ALPHA_BLENDER);
31 Canvas::Fill(Rgba::BLACK);
32 image.Blit(0,0);
35 //Draw lightmap to the screen
36 glBlendFunc(GL_DST_COLOR, GL_ZERO); //I used the openGL version of this function because of a missing selectBlenders() in Blenders::Set() (Blenders.cpp in my 2.0 pre-compiled version, can't be bothered to recompile it right now).
37 lightmap.Blit(0,0);
39 Canvas::Refresh();
40 }
42 return 0;

It works. You will need a png, preferably the same size as the window (800*600). I used a beach :)


I tried the code in my game engine. It was really neat! ^^
One thing I don't know though...
It seems that it puts a very very dark black over the screen. The lights
light that up and I can see my character, etc under them, and works fine, but my question is:

How do I make it so I can control that black so that I can adjust it to the general light level of the screen?
The opacity value in ol::Blit() didn't work because alpha blender wasn't used
but that other one. Could I perhaps use an RGBA value for that in the call
to fill the lightmap canvas??

(btw, not telling it to Fill() it made for some neat and funny fx. ;D)

Jonatan Hedborg

Yeah, change the lightmap Fill to some other color to have an "ambient light".


Yup, that worked!

Looks like everything is working fine now.

I think I'm ready to fully implement the lighting. :D

Thanks very much to everyone who helped!

Paul whoknows

Any screenshots?:)


Well, I guess I can show this engine's work in screenshots or a download or something. :)

I still need to finish up a few things before I do so though.
I want to finish my map editor first. I like to make sure it's all nice and polished
before I show anything.

But I can at least state it's features here:

hires hand drawn 2D graphics (1280x1024 screen)
hardware accel,32bit RGBA color/blending (thanks to OL for this!)
realtime lighting
Weather effects
Ambient stereo sound
FMV support/Video objects
(full motion video/animation - can be used as a background,spell effect in RPG or a video, etc.. Video objects are used....say for watching something on a TV screen in a room, etc)
I really forget what else at the top of my head...
this engine is also modable for following genre formats:
Platform, Action RPG, Full RPG, 2D Shooter, Strategy RPG.

Hopefully a demo will be available soon. Probably at least a screenshot or two in the next couple of days, for demo it's hard to say; I don't know when the editor will be finished. I really need to get that all done to make more progress on it.

Thread #592012. Printed from