How to code a Colorlize filter by shader?

kumayu

Newcomer
I'm a game artist want to code a Colorlize filter.
But don't know how to start.

I want to use a gray texture and a color( texture or float4 color)
combine them to get a colorize image.
Just like we do in Photoshop layer blend mode "color".
that add color to a gray texture without darken or brighten it.

The opengl orange book lists a few filter codes for blending.
But there is no Colorlize filter.
Are there any tutorial or article talk about Colorlize filter?

Why I need it?
The benefit of colorize is save a lot of memory.
Our UI designer use a lot of textures for UI.
And most of UI are number or character bitmap can't not compress well by DXT5.
So they choose to use ARGB8888 uncompressed texture.
Most of them are the same pattern colorize by different colors.
I wish we can find a way to colorize the gray bitmap and save a few memory.
 
I think I understand what you are after.

What I think you need to do is to use a different color space. If you convert your texture to be HSL then you can use your grey texture as the Lightness and the color is specified in terms of Hue and Saturation.

CC
 
I think I understand what you are after.

What I think you need to do is to use a different color space. If you convert your texture to be HSL then you can use your grey texture as the Lightness and the color is specified in terms of Hue and Saturation.

CC
I was actually thinking that he wants to use a palette texture.
 
I was actually thinking that he wants to use a palette texture.
I can see that.

You still have to calculate the pallete and give it to the hardware, which will be increased texture bandwidth (admittedly small)

My solution requires shader hardware, but to change the color being used only require two constants to be changed, rather than a whole palette.

I guess it comes down to where do you want to do the work, host or GPU?

CC
 
CC,
What I meant was that the OP has said that DXT5 (presumably it has variable alpha) does not compress the image data very well which implies, to me, very rapid changes of colour, in particular the hue. Images with low rates of hue change should otherwise compress well with S3TC based schemes. This would seem to suggest that HLS (or a even YUV) would not help terribly much either.

Simon
 
I will have to take your word on that. My knowledge of texture compression formats is minimal at best.

My approach came from a trying to mirror the way that they seem to be working. I.e. colorizing a grayscale image.

Also he mentions that the image data is mostly text, how would text be affected by DXT5?


CC
 
Just like we do in Photoshop layer blend mode "color".
that add color to a gray texture without darken or brighten it.

If I'm not mistaken, all that blend mode does is to compute color * gray. Should be very straightforward to implement in a shader (or even fixed function):

Code:
sampler2D Texture;
float4 color;

float4 main(float2 texCoord: TEXCOORD) : COLOR
{
    return tex2D(Texture, texCoord) * color;
}
 
If I'm not mistaken, all that blend mode does is to compute color * gray. Should be very straightforward to implement in a shader (or even fixed function):

Code:
sampler2D Texture;
float4 color;

float4 main(float2 texCoord: TEXCOORD) : COLOR
{
    return tex2D(Texture, texCoord) * color;
}

color * gray and color + gray not only change colors, also brightness.
" color * gray" would turn the image to be darker.
I want to colorize it "without changing in brightness".

For example , I can use the gray color vec3(128,128,128)
turn to a red color vec3(128, 0, 0).
Their brightness is same!
But that's simple single channel color case. not much usefull......
For three RGB channel case , I have no idea how to colorize a gray texture.

The HSL blend mode
http://www.entomology.umn.edu/museum/links/coursefiles/ENT 5051/PDF documents/Blend Modes.pdf

Color
Creates a result color with the luminance of the base color and the hue and saturation of
the blend color. This preserves the gray levels in the image and is useful for coloring
monochrome images and for tinting color images.

How to code a photoshop colorize filter in shader?
 
Last edited by a moderator:
DXT5 was not very good for image with a lot of color change in small area.
And our UI has a lot of text bitmap. Those text bitmap have Color Grads.
There are white edge and black shadow around text.
(all in a 16X16 or 32X32 area)
DXTn/S3TC compression can cause visable artifacts.
In other game textures , artifacts is acceptable.
But UI need to be clear , no artifacts.

Does new GPU still support palette texture?
I had a try to save a palette texture by photoshop nvidia dds plugin.
And it not work.

Look like I need to convert the RGB color to other color space first.
Which color space suits the need ,
and computelly fast enough to be use in realtime?
(our target platform use a geforce6200 GPU which is sloooww in term of ALU power)
 
Last edited by a moderator:
Here is how I would approach it:

the intensity (is is the same as brightness?) of an RGB color is usually as I = C_r*R + C_g*G + C_b*B, where the C_r, C_g and C_b are the weighting factors (how you define them is up to you, usually it is 0.30R + 0.59G + 0.11B). Basically, you want I to be the per-pixel greyscale value G. Your task is then to find a factor a such that G = a*(C_r*R + C_g*G + C_b*B); they you can replace the pixel color with the RGB tripple a*RGB and the intensity stays the same!

So the correct formula will be imho RGB_result = G/(C_r*R + C_g*G + C_b*B)*RGB
 
Most 3d hardware should be able to handle palette textures quite easily I beleive.

Keep your greyscale texture as it is.
Take your rgb color that is to be applied to it, and calculate the Hue and saturation using the formula here
http://en.wikipedia.org/wiki/HSL_and_HSV

Now you can either pass these as shader constants to a shader that does HSL->RGB conversion using the formula in that link. Or you can generate the palette by iterating through using the Palette index as the lightness value.

CC
 
Does new GPU still support palette texture?
Not natively. The indirect memory accesses are unpleasant to do in hardware and so were dropped several generations ago.

You may, however, be able to do your own version of palette textures by using texture lookups in the pixel shader (i.e. use point sampling to obtain the index and then use that value to access a second texture) but I'm not sure how you get cheap texture filtering with such an approach.
 
For example , I can use the gray color vec3(128,128,128)
turn to a red color vec3(128, 0, 0).
Their brightness is same!
But that's simple single channel color case. not much usefull......
For three RGB channel case , I have no idea how to colorize a gray texture.
Just multiply with the color you want, given at full "brightness" (value in HSV).
 
Not natively. The indirect memory accesses are unpleasant to do in hardware and so were dropped several generations ago.

You may, however, be able to do your own version of palette textures by using texture lookups in the pixel shader (i.e. use point sampling to obtain the index and then use that value to access a second texture) but I'm not sure how you get cheap texture filtering with such an approach.

Hehe, shows what I know about 3d hardware! :) I thought that palettes would have been easy

Why use point sampling to get the index?
 
I can understand that in the case where the palette consists of unrelated entries, you don't want to use interpolated values for the palette entries. But in this case the palette is a gradient of related colors.
CC
The first case still applies. Even if the colours could be arranged along a single line through colour space, you'd have to truncate your interpolated index value in order to do the lookup and so, unless you do the blending manually (with additional lookups), you'd end up with point sampling anyway.

Finally, if the texture is so simple that you can represent by a straight line through colour space, then it should compress extremely well with DXT.
 
The first case still applies. Even if the colours could be arranged along a single line through colour space, you'd have to truncate your interpolated index value in order to do the lookup and so, unless you do the blending manually (with additional lookups), you'd end up with point sampling anyway.

Finally, if the texture is so simple that you can represent by a straight line through colour space, then it should compress extremely well with DXT.

Using the HSL color space should give us a straight line through the color space along the line of the palette (although I don't know about the spacing of entries along the line....)

If the pixel falls on the boundary between two samples which are more than a single luminance value apart (which seems likely as he is talking about things like character bitmaps) then would you not want to take the interpolated value, as otherwise it will be blocky and horrible.

CC
 
Back
Top