🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

High Quality Lighting in a 2D engine

Started by
2 comments, last by Prgrmr@wrk 18 years, 2 months ago
To give background, I've been working on a 2D engine for about 5 months now. It's not intended for any particular game, rather, it's intended for any sort of 2D game (sidescrollers, shooters, RPG, RTS, etc). My main goal with this engine is to make it look as good as possible, much like if old SNES games were to be rewritten for modern hardware. Right now, it can do just about everything you'd expect, except for lighting, joysticks, and sound. Except for polishing, and some of the GUI classes for menus and fancy button styles, I'm nearly done. The problem I'm stuck on right now is how to do lighting. The 8 lights OpenGL allows you with the built in routines just aren't enough, and I can't be certain that recycling those lights constantly would be efficient, or look right in all situations. Ideally, what I'd like to do would be to use light maps from textures to brighten the proper areas, by drawing them into another drawbuffer, and then combining them with sprites and textures as they're being drawn (by color multiplication). Stencil buffers obviously won't do, since those are only bitplanes, not full RGB buffers. The accumulation buffer is what I'd really like to use, but without the ability to multiply the 2 buffers together (so that a pixel in the accum buffer of 0xFFFFFF would be full brightness, and something like 0xCCCCFF would be lighting with a blue tint) that idea doesn't work. I need some help with this. Am I missing something obvious, or is there a completely different algorithm I can use?
I know enough about OpenGL and game programming in general to be good at it, but not enough to always be very helpful, so I apoligize if I suggest something stupid.
Advertisement
2D lighting. You probably don't want to use the accumulation buffer as it's not available on anything other than really high end hardware. But you can still abuse the alpha component of the framebuffer for temporary storage. Or depending on your shadowing you might just be able to use lots of multitexturing and several accumulated passes.
Try using FBO's, they work like magic, if you have the hardware.
I used the algorithm provided in OrangyTang's link, except that I was able to modify it to do all the rendering in one pass (instead of one pass per light), or 3 passes if colored lights are desired. Unfortunately, using the alpha buffer for lighting meant glBlend wasn't able to draw anything translucent anymore. If anyone's curious, the algorithm is:
1: Disable writing of RGB components of the frame buffer, set all alpha pixels to the ambient light intensity.
2: Draw all applicable light maps/textures into the alpha channel, using a GLblend(GL_ONE, GL_ONE), so that all bright areas add up properly. Shadowing can be done for each individual light by using a stencil buffer, before drawing the current light.
3: Disable writing to alpha component, enable RGB components. Set glBlend(GL_DST_ALPHA, GL_ZERO).
4: Render the scene. Unlit objects can be drawn by setting glBlend back to the normal (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA).

To draw textures with transparent areas, I switched to alpha filtering, which didn't cause a noticeable speed hit.

To do colored lights, repeat the steps above 3 times, each time substituting the R,G,or B components of the light for the alpha value to write into the frame buffer. Then render the scene enabling writing for only that one color component.


Thanks very much for the help, I might never have thought of this.
I know enough about OpenGL and game programming in general to be good at it, but not enough to always be very helpful, so I apoligize if I suggest something stupid.

This topic is closed to new replies.

Advertisement