PolyCrunch Games are the developers of Pyramid Plunge, a cartoony rogue-lite, action-platformer with handcrafted pixel-art. They join us on the blog to share the way they use normal maps to bring awesome lighting their upcoming game.
Introduction
Using 3D shading techniques when making 2D games is an interesting one to create immersive environments that react to dynamic light sources. I'm using it in my game Pyramid Plunge for lighting the environment. However, I'm not using it on the characters, as I wanted to keep them looking cartoony and thus flat shaded.
How it works
You will need a simple shader that calculates shading similar to how its done in 3D, but instead of reading normal information from the 3D object or normal maps applied to 3D objects, we supply the normal maps as sprites. At the end of the article you'll find a sample project to play with.
But what are normal maps?
In 3D, a normal is just the direction perpendicular to the object's face or polygon. In 2D it will be the normal direction for that particular pixel being shaded. This information helps the shader to calculate how the light bounces on the object towards the camera.We can also add specular lighting which are those highlights typically found on metals. You would need another map called the specular map, and feed it to the shader too. But to keep it simple, we'll avoid specular for now.
So how can we achieve this in GameMaker?
First we need draw everything on a surface which will be only the color information (aka diffuse or albedo in 3d). We'll call this the Diffuse Pass. Then we need to draw all the normals information of each object on another surface. We'll call this the Normals Pass. (We could also have a 3rd pass for the specular pass if we wanted to)How to draw/generate the Normal Maps
1) Auto-generators
You can use tools like the free opensource tool Laigter. There's also NormalMap Online. But the problem with auto-generating is that they try to guess 3d data from 2d image. You can try to see what they'll come up with, but sometimes it's just not enough.
2) Manual drawing
You can use any drawing tool. Just have a reference of the normal map sphere. Aseprite has a normal map mode too where you pick a color from the sphere and just draw away. You can also draw manually with Laigter.
E.G. for this crate, the left side's normal would be something like the above picked color (my shader expects the Red channel flipped!).
3) Using a 3d modelling application.
You can also use Blender which is free to download and use. There are some good tutorials for the basics. I've used Blender for the columns in Pyramid Plunge. I generated the model in 3d, then after setting it up to export normal maps information, I could easily adopt them for the game.
Sample Project
Known Limitations/Disadvantages
- The shader will have a limited number of light sources. This number is set in the shader and is currently set to 8 (can probably be increased).
- There is some getting used to at first since you're drawing on surfaces. So if you have a camera, the drawing positions need to be offset by the camera position accordingly.
- If you want smooth shaded light, just disable the graded attenuation in sh_normal.
- Be careful of red channel in normal maps. Shader in sample expects it flipped when generated with tools. You can easily change it.
Also it would be awesome if you wishlisted Pyramid Plunge on Steam!