Thursday, March 17, 2016

opengl - Palette reduction to pre-defined palette


I'm writing a bunch of GLSL effects for fun, but I can't wrap my head around this. Basically, I want to reduce a texture's palette into a pre-defined set of colors. For example, a post-processing shader would take the FBO result texture and a 1D / 2D texture that would contain the reduced palette (say, 64 colors), and the output would then be sampled based on these.


Something like this in its core:


sampler2D source;
sampler2D palette;

vec4 source = texture2D(...); // Source texture to sample

vec4 palette = texture2D(...); // Palette

vec3 result = /* color from the source converted to the closest value available in palette */;

Any ideas how to do this? And to be more precise, I don't mean palette swapping - the source texture is full-colored result, and this shader would ultimately be a post-processing shader, reducing the amount of colors to the ones that are predefined in the palette texture.



Answer



Another way to do this is to make a texture that maps each RGB to a colour on the palette, an image like this (from the NES colours):


NES colour palette in a different shape


Then in a post processing shader you can the RGB colour from your regular image in a way like this:




uniform sampler2d paletteMapping;

vec3 mapColor( vec3 realColor ) {
vec3 mappedColors = floor( realColor * 16 );
int mappedI = mappedColors.r + mappedColors.g * 16 + mappedColors.b * 16 * 16;

return texture2D( paletteMapping, floor( vec2( mappedI / 64, mod( mappedI, 64 ) ) );
}

I've not tested the shader as I'm at work, but this should work on a texture that has interpolation disabled (i.e. it uses nearest neighbour sampling).



The map image I created with a little tool I wrote, from the NES palette image on wikipedia


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...