- Home /
How to make Textures Lighter/Reduce Color in 2D.
Hi,
I have an issue that I can't figure out how to reduce color in textures without making those transparent or darker. Currently the effect I want is created by changing Alpha of the texture, which looks as I want it to look, but at the same time background objects are shown through the forefront object, which isn't something I want.
In the picture you can see that in the area surrounded by red line the image in background, in this case cloud, is shown through the ground texture. This isn't something I want. However, if you compare the color of ground (the opaque ground on which the ball, trees and bushes are) to the background ground (the semi-transparent ground) you can see there is a difference in color. The shallow/lighter/colder/reduced color is something I want to achieve without making the texture transparent.
There are few solutions I've come up with, but not yet tested.
Creating a second texture just behind the mountain layer which is just the size of the layer I want to reduce color from AND the same color the background of that area is, without clouds. I.E. create a second mountain range and transform the color of that area to the same as in the light-blue sky. The fading would be done, but since there is a second layer just behind which is opaque, the clouds wouldn't be seen through.
Create a custom shader which would calculate the color as if it was faded in but yet keep the texture opaque.
The reason why I asked, is that I think that there is already a tool for reducing the color but that I just haven't found it. The problem is so specific that using Google brings me to threads which have more to do with using Alpha than reducing color and I can't think of anymore search words to use. This problem has pestered me for two months now (I've progressed in other problems while periodically returning to this).
Answer by CHPedersen · Nov 12, 2014 at 12:19 PM
What you're looking for is actually a reduction in saturation. You want to desaturate the colors in that texture, but doing so is unintuitive when colors are in RGB representation.
Try to open the texture in a standard image processor, e.g. Paint.Net or Photoshop, then lower the saturation, just to confirm that what happens to the image is the effect you desire in-game.
To do it to a texture in-game, the most intuitive way is probably to convert the RGB color representation to HSV/HSL, lower the saturation value of it in this representation, then reconvert it to RGB and save it back to the texture.
The algorithm for converting back and forth between RGB and HSL is very simple. There's sample code at this site to help get you started:
HSL is right way to go, since changing the Light level higher in Paint.NET has the desired effect on the texture.
However, it seems that in Unity the texture has RBG(A) Color of 255, 255, 255, 255 by default. Using the algorithm you gave would result in S going less than 0 or L going over 1, which would cause an error when converting back to RGB (R, G or B values can't go over 255). Changing the color of whole texture in this way won't work.
RGB => HSL ... var_$$anonymous$$in = $$anonymous$$( var_R, var_G, var_B ) var_$$anonymous$$ax = max( var_R, var_G, var_B ) del_$$anonymous$$ax = var_$$anonymous$$ax - var_$$anonymous$$in
L = ( var_$$anonymous$$ax + var_$$anonymous$$in ) / 2 if ( del_$$anonymous$$ax == 0 ) { H = 0 S = 0 } ...
HSL => RGB ... if ( S == 0 ) { R = L 255 G = L 255 B = L * 255 } ...
And since RGB == 255, 255, 255 and each var_X is 255/255 = 1 then L = (1+1)/2 = 1.
Having multiple physical copies of every texture isn't something I would like to do.
Edit: Yes, the algorithm works fine but Saturation can't be reduced or Light increased without causing an error when converting back.
The Paint.Net Color Picker looks like this:
If I grab any of the three sliders in the HSV section and change the value, the values in the RGB section above change alongside it. There is clearly an RGB value that corresponds to each HSV value, and Paint.Net clearly uses a conversion formula internally which you need to get your hands on. :) I was hoping the code samples in the site I linked to would provide the same conversion, but I'll admit I didn't test the math. If it causes errors when converting back after a desaturation, it is a flaw in the code sample, and not an inherent limitation in the mathematical idea. If the math didn't work, Paint.Net's Color picker wouldn't, either. So we simply need to look for another example, then. Perhaps the mathematical explanation offered in the Wikipedia article helps?
The effect I wanted was achieved by using HSL adjustments found from Paint.NET.
The conversion formula in Colors panel in Paint.NET is probably the same you already posted. The thing is, by default Unity handles sprite texture objects as if those were completely white (255,255,255 in RGB) and opaque (alpha 255). Since values can't go over 255 you can't lighten (whole) sprite texture objects using Unity's color adjustments without having to create a script which looks into each drawn pixel and recolors it accordingly, which is something I want to avoid as well.
Yes, I could use Paint.NET to recolor a set of textures and then implement those in the project assets, but that would require more memory when installing the client. This isn't something I want to do because the game is a mobile game.
Oooooh, then I understand. I was under the impression you were actually looking at accessing the individual pixels in code and recalculating them. If you want to avoid doing so, then desaturation in a shader is probably the most efficient way.
In your question, you mention that you're getting the desired effect by turning down alpha, which seems to indicate that alpha < 1 washes out the colors the way you want, you just want that to happen without the transparency. That means you could write a simple surface shader that multiplies the rgb channels of the texture color with the alpha, but leaves the transparency at 1. That might give you the desired effect and get rid of the transparency, while being very efficient on mobile, too.
There are good surface shader tutorials in the docs if you're unfamiliar with the way they work.