Search Unity

Shader: color replacement in a pixel-art context

Discussion in 'Shaders' started by lvictorino, Feb 7, 2014.

  1. lvictorino

    lvictorino

    Joined:
    Jul 9, 2012
    Posts:
    31
    Hello there,

    (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?)?

    I've found this color replacement shader on this forum, but I can't find a way to adapt it to my needs.

    Help would be appreciated.
    Thanks a lot.
     

    Attached Files:

    Last edited: Feb 7, 2014
  2. imaginaryhuman

    imaginaryhuman

    Joined:
    Mar 21, 2010
    Posts:
    5,834
    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.
     
  3. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,355
    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.
     
  4. lvictorino

    lvictorino

    Joined:
    Jul 9, 2012
    Posts:
    31
    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 :/
     
  5. lvictorino

    lvictorino

    Joined:
    Jul 9, 2012
    Posts:
    31
    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 :/
     
  6. mouurusai

    mouurusai

    Joined:
    Dec 2, 2011
    Posts:
    350
    Hello, maybe this can help you.
     
  7. imaginaryhuman

    imaginaryhuman

    Joined:
    Mar 21, 2010
    Posts:
    5,834
    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.
     
  8. lvictorino

    lvictorino

    Joined:
    Jul 9, 2012
    Posts:
    31
    Hi guys.
    Thank you so much for the help.
    I'll give a try to mouurusai example.

    Cheers
     
  9. fahd

    fahd

    Joined:
    Aug 7, 2014
    Posts:
    31
    did you manage to do it because I'm trying to do something similar