Using Sprite Lamp with engines

Sprite Lamp is a tool for making normal maps. Normal maps are a way of encoding the orientation of the surface at every pixel, with something called a surface normal. This is a fairly standard way of doing things, and in general, a modern game engine that makes use of dynamic lighting will usually allow you to use normal maps out of the box, including normal maps created in Sprite Lamp. The fact that Sprite Lamp is usually used to apply normal maps to a sprite doesn’t make any real technical difference – you’re simply applying it to a ‘billboard’ mesh (a rectangle that is positioned to face the camera) rather than a more normal mesh.

However! Sprite Lamp’s preview window shows some fancy effects which make use of other types of maps, such as depth maps. I have implemented special shaders in Unity and Game Maker that allow you to make use of these effects in your game. Game Maker doesn’t have native lighting support, so making a fully illuminated game in that engine will involve a bit of work (beyond what I’ve already done), but it’s entirely possible with some scripting know how.

Contents

Unity

Unity currently has the most developed versions of the Sprite Lamp shaders. You can get the sample project here, which includes a package file for importing just the shaders. Getting some use out of them should be pretty straightforward. These directions are for creating something from just the shaders – the alternative method is to simply open up the example project and poke around to see what’s there.

I’ll also note that this tutorial is for using Sprite Lamp in Unity’s 2D mode, with Sprites. Most of the features should work fine in Unity 3D, though.

Open up your art in Sprite Lamp, and generate/save out whatever maps you deem necessary. The important thing to know here is that for Unity, you’ll want to have the Flip Y (invert green) checkbox unchecked before you hit ‘generate normals’. I put that in bold because I’m pretty sure I got that backwards in the Sprite Lamp manual – sorry! It’ll be fixed shortly. If you want a depth map too, after you’ve generated it, select ‘depth’ from the ‘Normal map alpha’ pulldown menu. Once that’s done, hit ‘Save normal map’. This will save the normal map, and if you’ve generated a depth map, it will be put into the normal map’s alpha channel – the result will have the suffix ‘NormalDepth’. The Unity shader also supports ambient occlusion, so create an AO map now if you want and save that out too.

You should now have a diffuse map that you painted yourself, and at least a normal map from Sprite Lamp. Open up your project in Unity (or create a new one), and import the Sprite Lamp package. This is done by going to the Assets menu, selecting ‘Import Package’, selecting ‘Custom Package’, then navigating to the Sprite Lamp package you downloaded earlier. It should come up with a couple of shaders (some are different shaders, some are essentially the same but with different features enabled).

You’ll also want to import your images that you created with Sprite Lamp, of course. You should set the texture type to ‘Sprite(2DuGUI)’. Resist the temptation to set the texture type to Normal map, even if you’re importing the normal map. For pixel art, you’ll probably want to have the Filter Mode set to point, but that’s optional. You might also want to set the format to Truecolor – some image types it’s okay to leave as Compressed, but for the Normal or NormalDepth you’ll probably want Truecolor for quality reasons, especially with pixel art. If you’re using palettes, you definitely don’t want to compress the palette because the result tends to look horrifying.

Grab your diffuse map and drag it onto the scene. This should create a game object with a sprite attached. This is a good start, but obviously lacks the pixel lighting goodness that we’ve come for.

Create a new material (Assets->Create->Material) and name it something appropriate. In the inspector, you should be able to see a place where you can choose your shader (it’ll start as ‘Diffuse’ or something like that). Go into that menu, go down to ‘SpriteLamp’, and select ‘Standard’ (or one of the other Sprite Lamp options, if you’re feeling fancy).

Once this is done, you’ll have a bunch of options in the material. The most obvious are the slots for putting textures. You’ll need to drag your diffuse map and your normal (or normal/depth) map into their corresponding areas. If you have specular/gloss, ambient occlusion, or emissive, drag those into place too.

You can now drag your material onto the sprite game object you created earlier (or assign it in one of the other conventional ways). At this point, you’ll want to create a source of light in the scene. There are various options – go to GameObject->Create Other and choose one of the lightsources. Avoid area lights, but point lights, spot lights, and directional lights should all work fine.

Game Maker

Game Maker surprised and impressed me with the completeness of its custom shader solution, given that it’s not an engine designed for high end rendering. That said, it does take a bit more work to get going, because there are certain things (like a lighting system) that you have to maintain yourself, and as such this integration isn’t quite as far along as the Unity one, but if you’re feeling even slightly adventurous you should be able to get something cool happening. The Game Maker integration comes in the form of a Game Maker file, containing all the examples, as well as a bunch of text files containing scripts and a readme telling you where to put them (because I haven’t entirely wrapped my head around the correct way to package assets in Game Maker yet). Update: With the help of one K. Alex Mills, there is now an example of up to four lights working in Game Maker.

The instructions here are mostly copied from the readme.

Open up your art in Sprite Lamp, and generate/save out whatever maps you deem necessary. The maps that Game Maker’s shaders expects are the same as the Unity ones, which means that you don’t want to invert the Y component of the normals. If you want a depth map too, after you’ve generated it, select ‘depth’ from the ‘Normal map alpha’ pulldown menu. Once that’s done, hit ‘Save normal map’. This will save the normal map, and if you’ve generated a depth map, it will be put into the normal map’s alpha channel – the result will have the suffix ‘NormalDepth’. Ambient Occlusion maps are also supported in Game Maker. Note that unlike the Unity shader, the Game Maker shader doesn’t at this point support palettes.

In your game maker project, import all the textures you’re going to use as sprites.

Create a new shader called ‘SpriteLampShader’ and copy over the vertex and fragment shaders’ text. (The name is important, because the scripts reference it).

Create a dummy object in your scene called ‘light source’. Attach the light source scripts to the relevant events (there’s a ‘create’ and a ‘draw’ script).

To create game objects in your scene that get lit, add a sprite object like you normally would, using the diffuse texture as the base sprite. Then, attach the lit object scripts (again, there’s a ‘create’ and a ‘draw’ script for those, too).

About halfway down the ‘create’ script for lit objects, you’ll find a place where you should set your textures by name (currently it uses stuff like “sStoneWallNormalDepth” – you need to set them here yourself). Further down, you can set values of variables as you see fit.

You can also change a few variables on the light source in its ‘create’ script, such as colour and z position (actually those are the only two). Don’t add multiple lights, though – they don’t work yet.

Limitations

There’s a bug with the way the light position is calculated that causes slight stretching of the attenuation (it gets distorted by the aspect ratio of the screen). It’s a bit weird. I’ll probably have to rethink how this works.

Per texel lighting isn’t done yet, owing to the fact that the above bug needs fixing and will probably change how I go about this anyway.

The shader is just one big shader with everything in it – turning off visual features has to be done by editing the shader.