Are you a fan of computer graphics from the olden days of video games, before artists had the full gamut of 16,777,215 colors to play with and were instead constrained to palettes of up to 256 colors to choose from? Do you wish you could achieve fancy artistic effects by simply replacing colors in the palette of a single sprite? Do you wish this effect could be performed blazingly fast, and easy to combine into other shaders to boot? You're going to enjoy this!
You can find the Github repository featuring code for the demo here.
The system requires a bit of setup to use.
Sadly, GameMaker doesn't support indexed color natively as all textures are encoded as RGBA8 when you build the game, but there's nothing to say that we can't spoof it ourselves by simply using different grayscale values for the indices.
First, use the Lorikeet Editor tool to extract color palette information from a sprite, and then save both the palette and the indexed version of a sprite. Load both the indexed sprite and the palette sprite into GameMaker. Call lorikeet_set() with the palette sprite you want to draw with, and then draw the indexed sprite. The indexed sprite will be drawn with the specified palette. So will anything else you draw afterwards, so when you're finished call lorikeet_reset() (or shader_reset(), which lorikeet_reset() is simply an alias of).
lorikeet_set() accepts a few optional arguments, such as the palette "slot" you want to use, or the shader you want to set, if you've created additional shaders based on the main one. See the documentation.
You can also smoothly transition between two palettes in the same palette sprite, as seen in the demo when transitioning between day and night. I find this rather useful.
I've tested it on Windows, Linux (including the Raspberry Pi), OperaGX, and HTML5, and they work correctly on each of those platforms. By all accounts it should work on pretty much every other platform, including consoles, but I haven't tested it.
Runs on GameMaker 2022 LTS or later. It may work on older versions but I haven't tested it.
The Lorikeet shader is extremely fast. It's about five lines of GLSL, two texture fetches, and contains no loops, branches, or other things that makes the angry denizens of StackOverflow come out of the woodwork to personally attack you. Download the executable demo for a stress test.
With this said, batching is still important. Calling lorikeet_set() sets various shader uniforms and brings with it the same consequences as any other functions that affect the GPU state, and calling it every time you draw a sprite will likely incur an awful lot of batch breaks.
Depending on how you use it, this can also save quite a bit of space on the disk and texture memory, since you only need a single (grayscale, easily-compressible) version of your sprite with a small amount of palette data instead of multiple copies of the same sprite for each palette. The source files of all of the graphics in the demo took up about six times as much space as the indexed versions and their palettes.
Questions and answers
- The heck is a "lorikeet?"
It's one of the more colorful members of the parrot family, though I imagine that if you were actually wondering that you'd have looked it up by now.
These two systems are designed for different purposes. Jon's can easily be dropped into an existing project and allows you to replace colors in an already sprite without modification, but it isn't super performant in large quantities. This one requires a bit of setup, but performs extremely well (see the demo).
- Can I have more than 256 colors in a single palette?
Technically the shader could be edited to allow this, but I'm not convinced it's a good idea. A palette with many hundreds or thousands of colors in it would start to run against the aesthetic of pixel art with constraints. If someone makes a case for why this is needed this I might edit it in, but I wouldn't count on it.
- Do the palette sprites have to be on their own texture pages?
- Can you add [insert tool here] to the palette editor?
can be found here.
As usual, the asset is free as-is. I'll fix simple or game-breaking bugs but more involved support requires payment via either Itch or Patreon. I get the final say in what constitutes "game-breaking."
- The editor makes use of Emu (also by me), which uses Scribble by @jujuadams
- parakeet by Saeful Muslim from NounProject.comNounProject.com
- Demo things: