2
votes

In my 2D tile based game, the player can paint tiles to change there color. The simple approach (and what I have already done) is to use the tint parameter in SpriteBatch.Draw.

This looks nice, and here is an example:

enter image description here

But say, I want to paint the wood white. If you have ever messed with the tint, you know this isn't possible using the tint parameter. Color.White will tint the sprite the default color, and not white. This isn't a major problem, but I suppose some users might want it.

My question is, is there a method to color a sprite based on hue/saturation instead of tint. Similar to the "colorify" function in GIMP.

http://gyazo.com/eaa8d54d82a15ce05b006b084e71803f.png

An obvious approach would to be to use this function in GIMP and just export sprites for each color. The trouble comes in at the fact that this would take forever to do for all my sprites, and each sprite has multiple variations, meaning you could have in total 100+ combos for one block type.

Is this possible? I suppose a shader might get the job done.

2
Why don't you make the base sprite as bright as possible (nearly white)? You could achieve arbitrary effects with a pixel shader, but I doubt that this is necessary in this case. Gimp uses the same technique as the tint parameter, in my opinion.Nico Schertler
Look into the HSV color model: link. You can convert your texture from RGB into HSV, apply an offset to the Hue to change color, and then convert it back to RGB. Although it would definitely be easier to just have your texture be bright white to start, and use the built in XNA tinting.foolmoron

2 Answers

4
votes

The "colourify" function in The GIMP simply does a desaturate (convert to grayscale), followed by a colour multiplication. Very simple. This should be the equivalent HLSL (untested):

float4 original = tex2d(...);
float q = (original.r + original.g + original.b) / 3;
q /= original.a; // optional - undo alpha premultiplication
return float4(tint.rgb * q, tint.a * original.a);

But you could achieve the same effect by simply storing all your textures desaturated to begin with and using the default SpriteBatch shader for its multiplication. If you don't want to modify your source art, you could do it in a custom content processor.


Although, if you want to use a custom shader, you can do something more sophisticated. You could implement a full hue-rotation (kinda complex). But perhaps you could consider something like the "Overlay" blend mode (very simple) - which lets you colourize the grays, while preserving both the highlights and lowlights (instead of multiply, which also colourizes the highlights).

1
votes

To continue using the tint in SPriteBatch.Draw. Just make your "paintable" textures grayscale. So the white wood would be your default, but you draw it with a tint that makes it wood-colored.

I often use this to make UI and team coloring :)

in case it is interesting, what the tint does is just to multiply each pixel in the texture by the color you choose.

example:
texture pixel is (rgba) [1.0, 0.5, 0.5, 1.0]
tint is [1.0, 0.5, 0.5, 0.5]
result is [1.0, 0.25, 0.25, 0.5] (half transparent and more red-ish)