SpriteRecolour, an open source sprite recolouring tool

· by Steve · Read in about 3 min · (449 Words)



While doing 2D gamedev work this week, it came to the front of my mind how nice it would be able to easily have multiple colour variations of sprites, without having to have multiple copies of the sprites themselves.

There are various ways to do this, but the one I wanted to explore was a classic palette swap technique; the sort of thing we would have used in the 16-bit days. It was required back then; all graphics were palette indexed so it came with the territory; palette swapping and cycling was par for the course.

Today our colour modes are far more flexible, but because colour is stored directly per pixel now we lost that useful little trick for recolouring things efficiently.

So I looked online, expecting to find that lots of people already made tools to help with this. It’s gotta be a pretty common requirement with all those 2D pixel art games around, right?

Maybe I looked in the wrong places, but I came up empty. I found this article which came closest to what I wanted, but it had too many caveats around making sure that you never used 2 colours with equal red values.

Be the change you seek

So I told myself I wouldn’t get into tooling again, but dammit if I couldn’t find what I wanted and figured I could bash something out relatively quickly.

My solution is SpriteRecolour. It can take any input sprite, and generate the assets required to render a palette-indexed version of that sprite at runtime, with the palette provided either as a texture (1D if < 256 colours, 2D if more, nearest power of 2), or as a list of shader parameters.

Obviously you can swap that palette at runtime to generate different versions, and even modify it on the fly; which my Unity demo does.

When generating the palette I sort it using a CIE76 proximity estimation, this tends to group similar colours together which makes editing the palette afterwards much easier.

I wrote the tool in Go, because I like that for tooling these days. You can use the result in any engine, on any platform. Don’t worry if you don’t use Go, I built versions for all platforms so you don’t have to, they’re on the release downloads page. Here’s what it looks like in action:


There’s plenty of discussion in the README about how it works, and you can also refer to a demo Unity project I created for a concrete example of how you might want to use it.

I hope it’s useful to someone!