A downloadable tool

Download NowName your own price

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.

Usage

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.

Supported Platforms

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.

Performance

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?

No.

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?

No.

  • Can you add [insert tool here] to the palette editor?

¯\_(ツ)_/¯

Documentation

can be found here.

Price

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."

Credits

StatusReleased
CategoryTool
Release date Aug 27, 2022
Rating
Rated 1.0 out of 5 stars
(1 total ratings)
AuthorDragonite
Made withGameMaker
Code licenseMIT License
Average sessionA few minutes
InputsKeyboard, Mouse, Gamepad (any)
LinksYouTube, Source code

Download

Download NowName your own price

Click download now to get access to the following files:

LorikeetDemo.zip 14 MB
LorikeetDemoLinuxARM.zip 13 MB
LorikeetDemoLinuxx86_64.zip 13 MB
LorikeetEditor.zip 4 MB
lorikeet.yymps 10 kB

Development log

Comments

Log in with itch.io to leave a comment.

Would you be able to explain how the conversion of the default sprite to its indexed format is performed? Lorikeet looks like a great tool and I wanted to integrate into a project I'm working on, but I'd like to create an "all-in-one" shader that first performs the index color conversion on a sprite's pixel and then calls the "GetLorikeetColor" function on that converted pixel value to get the correct palette value. Basically, I'm trying to do everything at runtime instead of using the editor to convert my base sprites to their indexed versions first (there are a quite a lot of sprites in my project and it would take a while to do that for all of them).

I tried combining the Lorikeet shader with the standard NTSC accurate grayscale shader on GameMaker's website, but I quickly realized that isn't what you used to perform the index conversion, so it didn't work. I'd appreciate some insight!

Getting the palette of a sprite at runtime isn’t something Lorikeet does (nor do I have any interest in doing so), though if you really want to do that there’s this one that Jon made. The color index is stored in the grayscale value. Look into how old video game consoles stored sprite color before the days of RGBA.

If you want to apply an additional effect after the palette lookup, modify the final gl_FragColor value.

I get that the color index is being stored in the grayscale value. I was just curious how the grayscale value itself is being calculated. I'm definitely not asking you to do any more work with the shader, but I figured that if I knew what calculations were being performed to get the indexed grayscale version of the sprite then I could write some additional shader code myself to do that conversion before calling the lorikeet shader code.

If that's not possible (or overly difficult) I could definitely look into using PixelatedPope's system instead.

The colors are indexed by counting all of the (unique) colors in the image and putting them in order. This can’t be done in a shader and has to be done ahead of time, but mapping the color onto the index can be done in O(1). Jon’s works by searching the palette for a matching color (or an almost-matching color), which is much slower but is usually good enough.

I just realized I never replied to this. Thank you for taking the time to offer clarification, I really appreciate it.

(1 edit)

Hi, I'm sorry to bother you again but I was doing some more work with Lorikeet and had a quick question. In the game I'm developing, my player character's sprites are separated into different strips based on animation (i.e. idle, jumping, running, etc.). Because of this I was planning on exporting each strip individually, importing it into lorikeet to get it's indexed equivalent, and then reimporting the indexed sprite back to GameMaker.

I noticed, however, that despite the fact that all the sprite strips share the same color palette, lorikeet has been giving each one I import a completely unique indexed equivalent which I wasn't expecting.  You can see it in the following pictures:





I was wondering, when making the indexed version of the duck sprite in your demo project, did you index an ENTIRE singular sprite sheet for the duck and then cut it up later in engine? Or did you have all the different animations as separate sheets and index them individually (like I was trying to do). I have a sinking feeling you did the former, which would mean the only way around this would be for me to export all the animations in my game, consolidate them to a single sheet, index them, then reimport and cut the sheet in-engine.

I did, yeah - though if it makes it any easier, I also made this little program to make cutting sprite strips into individual images faster: https://drive.google.com/file/d/1xlhksRYzESCeLnZEYLgLJDbIF53uRDay/view?usp=sharing