(First of all, you have to know that I suck at shaders, but I want to learn!)
Imagine a basket-ball game made in pixel-art style. I want to give the possibility to change shirts colors on the fly thanks to a set of proposed colors. For your information, shirts are composed of 16 colors.
I want to use two textures to perform this effect. An original shirt texture (obviously), and a “palette” texture composed of a grid of colored pixels (a grid of 16xN pixels where 16 are the shirt colors and N the number of color set available. ie: if [0][0] pixel of the palette is white, and [1][0] is blue, every white pixels of the shirt texture will become blue if player choses the color set 1).
Example of a (scaled) palette I want to use:
I immediately thought of an algorithm using GetPixels / SetPixels on the sprite texture. I’ve implemented it and it works fine.
BUT, I was wondering if such effect couldn’t be done using shaders (have I told you that I suck at shaders?)?
Color palette remapping is pretty simple. Your palette is a texture. Then you have your white shirt texture. Then it sounds like you want to apply a single color as a tint to all of the pixels in the white shirt, even if they are different levels of gray or whatever. Once you’ve got the color from the palette you can just multiply it by the white shirt pixel color. But getting the colors from the palette is the trickier part. Somewhere you’ve got to tell the shader which palette entry to read, based on a UV coordinate. You could have an index number input to your shader, which I think would mean each sprite using this would have its own draw call since they all would have different values? Or you could store the index of the palette entry somewhere like in another texture or in some vertex data like vertex colors. Or you could alternatively store the uv coords of the palette texel.
But it sort of also almost sounds like you could do this entirely with vertex colors, but then you’d have to modify your own sprite geometry meshes.
Since you’ve only got two teams, the memory/bandwidth overhead of having two sets of sprites is probably just less than the fill rate overhead of doing the replacement for every pixel every frame in a shader. I don’t think it would make much difference either way, though, so if what you’ve got works then I wouldn’t worry about it.
Hi Daniel,
In fact the basketball shirt case was just an example. In the game I’m working on I’ll have to replace colors of thousands of different textures… I will always have up to 4 textures to fill, but the color palette will surely be composed of 16x256 colors. I can’t afford to have 256 version of a thousand of texture
Sorry if my example was missleading
I think my post was not clear. As I want to change several colors of the shirt.
For example I want every white pixel to become blue ones, every red pixels to become green ones, every dark grey pixels to become light pink… and so on. 16 colors per shirt have to be changed.
Except that, I’m sorry but I think I have not understood your post
You basically need a way to convert your shirt etc image into palettized indexed color, and then have it lookup a palette texture. As mentioned in the above like you can either use RGBA to store indexes, or row/column offsets, or uv coordinates. Either way each shirt pixel etc then points to a specific place in the palette. I think though what you’ll need is to expand on it, by allowing you to choose somehow WHICH of many palettes to use. That’s what I was trying to explain. You have multiple possible remappings, not just one. So you need to store something somewhere that tells the shader WHICH of the palettes to look up. Also if you have multiple recolored sprites on screen each with some kind of setting in the material that’s object-dependent, then every instance will create a drawcall which could be bad. I think the best way might be to store something in the vertex data such as using vertex colors, then each instance of the sprite which will have its own mesh data would pull up the vertex colors as color-index data ie which palette to use.