Lighting in FPS games

I am using several lighting techniques for my FPS engine and would like to discuss these and any other options.

There are three kinds of “things” that get lit in my engine. First, there are characters and models that move around the level. Next, there are the CSG walls that make up the shape of the map. Then there are the high-poly “static meshes”, like what Unreal 2 uses.

Character models are the simplest. I am just using good ol’ GL lights. I do a test to see if the light and the character are visible to each other, so that characters don’t get lit by lights from another room.

Second comes the CSG walls, what maps used to be composed exclusively of in game like Half-Life. First, I create the map and calculate lightmaps in Cartography Shop . For dynamic lights on the walls, vertex lights would look lousy. Instead, I start with a circular gradient texture. I clamp the texture, so it doesn’t repeat, and map it to the wall, with an equation that transforms the x,y,z position of the light into UV coords on the wall. Then I render the lit wall in a second pass. It looks great, and isn’t very demanding, because CSG walls tend to have very few vertices to calculate the UV coords for. In fact, I bet you could do it without changing the UV coords at all, but rather by just positioning and scaling the texture.

Third are the high-poly “static meshes” that add detail to the map. I calculate vertex lights ahead of time, and always display those in the engine. I also use the dynamic lights, but instead of providing diffuse lighting, I use them to specularly light the static meshes. The meshes are already somewhat darkened, so diffuse light would only make them as bright as the pre-calculated vertex colors.

I’ve also had some success with “projection shadows”, mapping a texture onto a dynamic scene. Are there any other options I should be looking at, that are easy to implement? I think this is pretty much how Unreal 2 works, minus the dynamic shadows.

[This message has been edited by halo (edited 12-18-2003).]

Sounds reasonable. The choices you make are strongly tied to the hardware you target, and I wouldn’t recommend anything much more sophisticated than what you’re doing unless you intend to run only on DX9-class cards. One thing you could consider is to use shadow mapping instead of the projected texture shadows.

For the dynamic lights on the walls, it sounds like you’re calculating the texcoords on the CPU. I would suggest using glTexGen() instead, so the hardware can do it for you.

Also, I’m not 100% clear on what you do for the static detail meshes. You say you precalculate per-vertex lighting? What do you do if a dynamic light falls on them?

– Tom

I’ll look at GLTexGen. My routine has to transform the 3D coordinate to the wall’s 2D space, and is a little slow.

For static meshes, I combine pre-calculated vertex colors and GL lights.

What exactly does shadow mapping involve, I mean just the basic theory?

Thanks for the comments. If you want to see the lighting methods I talked about in action, click here .