Skip to main content
GameDev.net gamedev.net
🔒 Locked

colormath: Desaturation

Started by genesys Feb 3, 2006 at 12:10 AM 14 replies 27.8k views
Original Post
genesys
genesys
Hi! I want to desaturate my colors in a shader... the question is: What's the most performant way to do desaturation? I thought about converting from RGB to HSV and then back to RGB but the formulas i found on wikipedia look a lil bit complex - so i don't think that this is the best way to do it... Every Hint is appreciated! Thx!
genesys
genesys
hmmmm . . . 0.3, 0.59, 0.11 ? i don't understand...
Red_falcon
Red_falcon
Just multiply every color component with 0.3 for red, 0.59 for green, 0.11 for blue.

this are the values for color conversion to grayscale. search with google for color conversion and yo will find many other algorithms

here are some links:

http://www.easyrgb.com/math.html
http://astronomy.swin.edu.au/~pbourke/colour/
-----"Master! Apprentice! Heartborne, 7th Seeker Warrior! Disciple! In me the Wishmaster..." Wishmaster - Nightwish
genesys
genesys
sure? how can this be?? if you multiply plain white (1.0,1.0,1.0) with these values you get (0.3,0.59,0.11) which is green!?
Kalidor
Kalidor
Quote:
Original post by genesys
sure? how can this be?? if you multiply plain white (1.0,1.0,1.0) with these values you get (0.3,0.59,0.11) which is green!?
No, you do a dot product of the color and (0.3, 0.59, 0.11) to get a grayscale intensity value. If you were converting to grayscale you would set each color channel to this intensity. What the AP was suggesting is to get this grayscale intensity and then linear interpolate between it and the original color to get your desaturation.
quasar3d
quasar3d
Quote:
Original post by genesys
sure? how can this be?? if you multiply plain white (1.0,1.0,1.0) with these values you get (0.3,0.59,0.11) which is green!?


1 * .3 = .3
1 * .59 = .59
1 * .11 = .11
----------------+
intensity = .3 + .59 + .11 = 1

r = intensity
g = intensity
b = intensity
someusername
someusername
if you're just trying to change the image into grayscale, I believe that taking the average of the r,g,b channels and replacing them with it, should work.
m = .33333f*(r+g+b);r=g=b=m;
genesys
genesys
I don't want to desaturate the colors completely! just a lil bit!
Matei
Matei
In that case blend a little between the completely desaturated colour and the original colour. Do something like 0.9 * original_color + 0.1 * desaturated_color.
genesys
genesys
oh ok! i understand!

taht's working :) thanks!

just one mor question: perhaps there is a less accurate but (for small saturation changes) working formula with less operations?
S1CA
S1CA
For more colour manipulation ideas using interpolation/extrapolation, see the following: http://www.sgi.com/misc/grafica/interp/index.html

Quote:
just one mor question: perhaps there is a less accurate but (for small saturation changes) working formula with less operations?


The linear interpolations posted above can be done with a single pixel shader 1.1 instruction, you won't find much less than 1![smile]

HLSL:
const float3 coef = {0.3, 0.59, 0.11};
out.rgb = lerp(in.rgb, coef.rgb, amount);

PS1.1:
def c0, amount, 0, 0, 0
def c1, 0.3, 0.59, 0.11, 1
lrp r0.rgb, c0.r, r0.rgb, c1.rgb ; r0=input and output
Simon O'Connor | Technical Director (Newcastle) Lockwood Publishing | LinkedIn | Personal site
S1CA
S1CA
Quote:
Original post by Anonymous Poster
Anonymous Poster: Not one instruction, you forgot to do the dot product:

(Without knowing exact HLSL syntax)

HLSL:
const float3 coef = {0.3, 0.59, 0.11};
out.rgb = lerp(in.rgb, dot3(coef.rgb, in.rgb), amount);


PS1.1:
def c0, amount, 0, 0, 0
def c1, 0.3, 0.59, 0.11, 1
; r0=input and output
dot3 r1.rgb, c1.rgb, r0.rgb
lrp r0.rgb, c0.r, r0.rgb, r1.rgb


AP: Oops, my bad, yep you're quite right.


OP: So if you don't already have the luminance of the source image elsewhere in your shader, you'll have to dot the input colour against the coefficients to get it.

That said, luminance being scalar does open up some opportunities for co-issuing, so in most non-trivial pixel shaders, I'd still expect the whole desaturation operation to take only 1-1.5 effective instruction slots (or to be able to tag some extra functionality onto the operation to save elsewhere).
Simon O'Connor | Technical Director (Newcastle) Lockwood Publishing | LinkedIn | Personal site

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.