3-Line Color Array Palettes, with Shifting

Compact, expandable, no conditionals bc GPUs hate those. Uses R channel of sprite color. Uses alpha from color array, multiplied against alpha from the base sprite.

For the standard <=11 colors, increment the R channel by 25 at a time for each color, up to 250. (Red at 25 == COLOR.r at .1 == colors[1])

For more colors, you could bump up the array allocation to [21], then increment the R channel by 12/13.

Be sure to set array_max if changing array size. It’s used to keep indices in-range after applying offset; out-of-range values will return vec4(0.0).

Use index_offset to shift up/down the color array. Different versions of return_index() provide different behavior, or disable this feature entirely. (see code)

For a highly detailed final product, you could use another color channel as a multiplier for the final RGB value, or as a mix()factor to shift towards a “shadow” color (or an array of them!)

Note: return_index()‘s default “Looping” behavior acts strange for index_offset values in the low negatives, effectively making them a deadzone. If incrementing offset downwards, you can start at -15 since the loop seems to work as expected from there, or just use descending positive values on repeat. (If you can tell me why this happens, please do, I’m at a loss here lmao)

Artist QoL — if the blue-green mess of the “true” color hurts your eyes, you can (for example) use indexed palettes in Aseprite to switch between more varied placeholders and our “true” colors.

Shader code
shader_type canvas_item;

uniform int index_offset;
uniform vec4 colors[11]: source_color;
uniform int array_max = 11;


// 	Swap out the following return_index() funcs to change index shift behavior.

//   LOOPING -- Out-of-range indices are looped around to the other side of the array.
//   Useful for flashing effects. If using negative offset values, start at -15.
int return_index(float raw) { return (int(round(raw * 10.0)) + index_offset) % array_max; }

//   CLAMPING -- Out-of-range indices are clamped to the edges of the array.
//   Useful for fading effects.
// int return_index(float raw) { return min(array_max-1, max(0, (int(round(raw * 10.0)) + index_offset))); }

//   NONE -- Disable index shifting.
//   You can also comment out the index_offset and array_max declarations.
// int return_index(float raw) { return int(round(raw * 10.0)) }


void fragment() {
	float alpha = COLOR.a;
	COLOR = colors[return_index(COLOR.r)]; // Red 25 == COLOR.r .1 == colors[1]
	COLOR.a *= alpha;
}
Tags
array, Color, colors, pallette, pixel, pixel-art, sprite
The shader code and all code snippets in this post are under CC0 license and can be used freely without the author's permission. Images and videos, and assets depicted in those, do not fall under this license. For more info, see our License terms.

More from laffcat

3-line Colormap Palletes

Related shaders

3D Post-Processing: Dithering + Color Palettes

color splash (show only one color)

Select Color Range

Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments