Pixel art is generally free from any post-processing effects, since artists try to simulate the old gaming systems where people didn’t have the freedom to draw out anything they want. Nevertheless, I’ve been working on some useful shaders for pixel art games, since it never hurts to have access to post-processing effects.
/**
* Convert input color to any bitrate.
*/
vec4 channelBitrate(vec4 inColor, int bit)
{
float bitDepth = pow(2.0, abs(float(bit)));
vec4 outColor = vec4(floor(inColor.r * bitDepth),floor(inColor.g * bitDepth),floor(inColor.b * bitDepth),floor(inColor.a * bitDepth)) / bitDepth;
return outColor;
}
Colors have 4 channels, R, G, B, and Alpha (transparency), and most modern devices use an 8 bit per channel for image files and displays. On old game consoles like the Gameboy, Super Nintendo, Genesis, and even the GBA, developers had to deal with tighter color requirements. The Gameboy only had 4 shades to choose from, the Gameboy Color had a 5-bit per channel display, and could display a maximum of 56 colors, though normally it was far less. This bitrate shader can change a color to any bitrate the user wants.
PalleteShader
/**
* returns color in alt pallete closest to inputed color.
*/
vec4 colorPaletteAlt(vec4 inColor, sampler2D texPalette, sampler2D texPaletteAlt)
{
vec4 outColor = vec4(0.0);
float minDis = 1000.0;
float dis = 100.0;
if (inColor.a > 0.001)
{
for (int i = 0; i < SAMPLES; i++) { vec4 palleteColor = texture2D(texPalette, vec2((float(i) + 0.5) / float(SAMPLES), 0.5)); //Map to HSL Space dis = sqrDistance(rgbToHsl(inColor).rgb,rgbToHsl(palleteColor).rgb); if (palleteColor.a > 0.001)
{
if (dis < minDis)
{
minDis = dis;
outColor = texture2D(texPaletteAlt, vec2((float(i) + 0.5) / float(SAMPLES), 0.5));
}
}
}
}
return outColor;
}
This is the base shader from which all my other palette based shaders are based off. All the shader needs is a texture that features a palette, and you’ll be able to do anything with that palette, from introducing alternative palettes, to changing the order or brightness of an image based on the palette.
The shader works by mapping the colors of the base texture onto HSL Color space, and performs a simple distance check on different colors to determine which colors on the base texture are closest to the palette. With this it’s possible to do alternative palettes, or parse unwanted stray colors from a sprite.
That’s about it for now, but be sure to follow me for more shaders and useful programming techniques!
~Alain