The biggest practical issue will be getting the actual index + palette data, whereas all the available APIs depalettize into RGB form. Do you need to bring in images dynamically, or will they be a fixed set? If the latter, you can preprocess them a bit to have this information on hand, e.g. as strings in your code or a database. (Maybe some tools can provide this to you. If not I can check some stuff of mine e.g. the stuff here to see what it might take.)
Depending on the number of colors you need, there are a few ways you could go about this. If you were going for an authentic Game Boy look, for instance, the vertex userdata would suffice to store your shades of gray. For anything else you'll probably want them in a texture.
For that matter, the way to go would be a couple of them:
- A width-by-height texture that will store your indices
- A palette size'd one, e.g. of size 64-by-1, storing the colors themselves (if you don't have a power-of-two size it's probably worth rounding up anyway and padding with dummy colors)
Memory bitmaps are a good fit here. The index texture can be rgb and the palette either rgb or rgba. You will want to set filtering to "nearest" when making your indices, since you don't want them blending. Possibly not the palette colors either, but that one's up to you.
If your palette is 256 entries or less, you can encode the indices in the texture's red channel. (If you need more than this, it requires some encoding, but can be done.)
Basically, assuming your indices start from 0, you divide them by the palette size and stuff the results, which will be values from 0 to 1, one by one as that shade of red (i.e. setting green and blue to 0) in the index texture. You put the colors themselves in the palette (at index 1, the color belonging to 0 / Size; at index 2 the one for 1 / Size; and so on).
Finally, make a composite shader with the two textures as inputs. Inside it, read the index from one and use it to look up the color from the other, so something like:
P_COLOR vec4 FragmentKernel (P_UV vec2 uv)
P_UV float index = texture2D(CoronaSampler0, uv).r;
return texture2D(CoronaSampler1, vec2(index, 0.));
To modify the palette, edit its colors or bind a different textures.
Some of what I mentioned in this thread might be usable here.