Normal Mapping for 3D-Like Lighting in 2D Games

I recently saw this video about a game engine that uses normal mapping to generate lighting and shadows for amazing, 3d-like lighting effects. (Like the three barrels below on the right side, they all use a single image, with lighting applied.)

After googling for some time and reading the articles, I'm not sure I understand exactly how this effect works -- that is, how I would implement this. It seems like you need your original image, plus a grey-scale "normal map", where the colour represents depth -- the "farthest away" pixels are black, and the "closest to the viewers" are white.

But even if I have this, how does this information combine with lighting to create that 3D effect?

Also, how would I use this information to create casted shadows (see bottom-left barrels in the picture below)?

• Are you sure it is normal mapping and not shadow mapping? Commented May 5, 2012 at 16:44
• Bump mapping is bump mapping, whether in 2D or 3D. It works the same way: you have a texture that provides a normal for the surface, rather than interpolating one from vertex positions. Commented May 5, 2012 at 16:53
• @bobobobo pretty sure. the author's website mentions that his engine uses normal mapping and focuses on quality lights/shadows. Commented May 5, 2012 at 20:32
• @bobobobo shadow mapping is part of it too. I'm more interested in the lighting part though. Commented May 7, 2012 at 2:56
• I don't have a full answer, but I found this while thinking about it, so I'm leaving a comment. You'd want at least a 2D normal map, instead of a 3D one like 3D object use, so it wouldn't just be greyscale. Since that's the case, might as well use a full 3D normal map. Then lights that are slightly "behind" the object can still light up things properly. Then I think it's just a matter of applying light according to how close the normal is to the direction of the light, and the distance/output from the light factors in, too. Commented Jan 21, 2013 at 19:20

I believe the name of "normal map" may be misleading (i'm not sure), the image itself contains color information which anything can be stored inside R/G/B/A channel and finally name the whole texture to anything totally different.

Anyway please take a look at this similar question. The first comment inside the link below may interest you.

How is 2D lighting implemented?

• I've read that link ages ago. It's about shadows, not about simulating 3d via normal mapping. You are correct that the image is pixels, and the channels (R, G, B) are used to store information, not necessarily colour. Commented May 5, 2012 at 20:33

It's close to the exact same as for 3D. If you aren't familiar with 3D graphics programming (including forward lighting, deferred shadong, normal mapping, and shadow mapping) then you should step back and study those topics first. They're all fairly easy; I'd argue that normal mapping is the hardest simply because you have to deal with tangent and binormal basis conversions, but they're just basic linear algebra.

From there, you need to do a few tweaks and simplifications to the algorithms. Assuming you aren't just using a full 3D engine will bill-boarded sprites, that is. First of course is to move from a 3D projection to a 2D projection (simulated using an orthographic projection matrix in a 3D stack combined with keeping all your objects locked in the XY place and oriented toward the positive Z axis). Basic 2D rendering stuff, nothing special at all, but with those 3D lighting algorithms applied in your shaders.

From there, you have a couple small tweaks to make. The most important is your light source location. If your lights are in the XY plane and your objects are in the XY plane and oriented perpendicular to that plane, the lights are going to look "weak". The lighting will look like you laid a flashlight on a table and are trying to light up pages of a book also laying on the same table. The tweak to make then is to simply move the light outward some distance; the distance chosen will need experimentation to find a nice looking value.