So, finally proper update today, and a new release of the Sprite Lamp Unity shaders to try out. Apologies to all for the time this took (and to anyone wondering, Snake Hill is just about ready for the fire season). You can get the new shaders at the Sprite Lamp engine page as usual. Here I’m going to write a few things about Sprite Lamp and Unity that might be relevant to you. I’m going to make a quick disclaimer here now though: I’ve been tinkering with Unity for a little while, but I’m not expert – if you read something here and think you know better, you may well be right, and please let me know!
Normal maps in Unity without special shaders
I think with all my talk of Sprite Lamp/Unity shaders, some non-technical (or just non-graphics-savvy) readers might have gotten the impression that you have to use my official Sprite Lamp shaders to use Sprite Lamp with Unity. This is not the case! Sorry if I communicated that poorly. Sprite Lamp creates normal maps, and pretty much any modern 3D game engine that supports dynamic lighting, including Unity, can work with normal maps. As far as the engine doing the rendering is concerned, applying a normal/bump shader to a sprite is no different to applying a normal/bump shader to a mesh. The key thing with Sprite Lamp is allowing normal maps to be created without 3D modelling, and in a fashion that maximally preserves the artist’s style – but at the end of the day, they’re still normal maps and can be used like normal maps! There are some special fancy shader effects that work well in conjunction with this technique – stuff like self-shadowing based on a height map – and I’m writing my official Unity Sprite Lamp shaders to support those effects. But, I’d say most people working with Sprite Lamp would get most of what they want with Unity’s built in shaders.
That all being said, this is simple enough to do. First thing you’ll need is a diffuse map and a normal map (which I’ll presume is made in Sprite Lamp, but need not be). Import both these images into Unity in the usual way, with the diffuse map set as the Sprite type, and the normal map set as the Normal type. It’s important at this point to uncheck the ‘Create from Grayscale’ checkbox on the normal map’s import settings, or else it will look (and be) incorrect.
From there, make a new material and set the shader as one of Unity’s built in shaders with ‘bump’ in the name, such as ‘Bumped Diffuse’. You can now drag your textures into the appropriate slots, and drag the material onto your game object. This can be a sprite you created, or a quad (or a mesh of some other shape).
The advantages of using Unity’s built in shaders are mostly that, now and in the foreseeable future, the people that built Unity understand Unity better than I do. They’re likely to have more complete support across all of Unity’s different iterations, different platforms, rendering backends, etc. and, if nothing else, can hopefully provide a fallback if my shaders aren’t perfect. The good people at Unity are likely better optimisers than me, too, especially for mobile platforms where it counts.
The official Sprite Lamp Unity shaders
There’s a detailed writeup of how to make use of the official shaders over at the engine integration page so I’m not going to reproduce that all here. What I will do, is describe what’s changed in this new update – in dot point form.
- Spine – My first attempt at a Spine shader is now included.
- Attenuation that works properly – To my mind, this was the biggest problem with the old shaders – they weren’t terribly usable when you couldn’t reliably avoid nasty hard edges from the lights going out of range. It should be sorted now. You still have some ability to tweak attenuation of lights on a per-material basis (which I still wish I could make a property of lights).
- Spotlight circles need no longer be hard-edged (how soft they are is also adjustable in the material properties).
- Optimisations – I’ve revamped how a few things work, and that should make things faster (fewer branches due to multicompile between different light types is the main thing).
- There are a few platforms that this didn’t compile on before that it now compiles on. If it still doesn’t compile for you, let me know (these things can be hard to track down).
I’ll also add that I’ve decided to keep the ‘several shaders with different features turned on and off’ approach, rather than attempting multicompile stuff, because as far as I can tell this would cause a mild combinatorial nightmare because it is also compiled five times for the different light sources.
Somewhat experimental Spine stuff
I’ve gotten some lit Spine stuff working at my end. I’m not sure that this is the best way to go about things, because I’m even less experienced with Spine and Unity together than I am with Unity on its own, but hopefully it will be of use to some people. It makes use of a fragment shader that calculates the normal/binormal/tangent matrix on the fly, so it can deal with deforming meshes without requiring a bunch of extra code on the CPU side to calculate tangents dynamically as they deform – not sure if that’s the best tradeoff (my guess is that it depends on the platform).
For this reason, it should be reasonably simple to set up, with one exception that I’ll get to in a minute. Start by setting up a Spine character (or whatever) in Unity the way you usually would – I won’t go over this here because there are better tutorials to be had by googling. When things are working as they should be (but without lighting), there’s one tricky thing to do (and thanks to ashwin911 from the forums here for putting me on the right track with this), which is setting your Spine object to have some Z spacing. This is because multipass lighting in Unity depends on the depth buffer, so we’ve got to give it different depth values. There’s a value called zSpacing that you need to set to some small negative value (ashwin911 suggested -0.001, which is what I’ve gone with in my example). The trick is, this value is hidden for some reason, so you need access to hidden variables. You can do this by going up to the “inspector” tab, right clicking, and selecting “debug”. Under the “Skeleton Animation” component, there should be the ‘ZSpacing’ value available to change.
Once you’ve set that to -0.001, you can create a material using the Sprite Lamp Spine shader, and assign your textures to it as usual. From here, assigning your material to your Spine character should be all that’s left!
The new attenuation stuff
I’ll just mention very quickly how I’ve set up attenuation. Basically, it works by calculating a linear drop off in intensity, that goes from one at the origin of the light, to zero at the max range of the light. It then raises this value to a power – you have control over that power, in the ‘attenuation exponent’ shader variable. If you increase this variable, the dropoff will happen suddenly, quite close to the light, then go to zero very gradually. If you lower it, it will drop off gradually at first then suddenly near the end. Lowering it all the way to zero will give you a bright sphere that drops to zero immediately at the maximum range.
Similarly, there’s a variable called ‘spotlight hardness’, that affects how hard-edged the circle of a spotlight will be. This is pretty self-explanatory – setting it to maximum will make the spotlight a hard-edged circle like it was in the older shader, and setting it lower will make it very soft-edged. Unfortunately, both these variables are attached to the material, not the light source (I’m not sure if it’s possible in Unity to attach variables to the light source).