# Hue, saturation, brightness, contrast effect in hlsl • ### Question

• Hi All,

I am new to pixel shader, and I am trying to write a simple brightness, contrast, hue, saturation effect. I have written a shader for it but I doubt that my shader is not providing me correct result, Brightness, contrast, saturation is working fine, problem is with hue. if I apply hue between -1 to 1, it seems to be working fine, but to make things more sharp, I need to apply hue value between -180 and 180, like we can apply hue in Paint.NET.

Here is my code.

// Amount to shift the Hue, range 0 to 6
float Hue;
float Brightness;
float Contrast;
float Saturation;
float Alpha;

sampler Samp : register(S0);

// Converts the rgb value to hsv, where H's range is -1 to 5
float3 rgb_to_hsv(float3 RGB)
{
float r = RGB.x;
float g = RGB.y;
float b = RGB.z;

float minChannel = min(r, min(g, b));
float maxChannel = max(r, max(g, b));

float h = 0;
float s = 0;
float v = maxChannel;

float delta = maxChannel - minChannel;

if (delta != 0)
{
s = delta / v;

if (r == v) h = (g - b) / delta;
else if (g == v) h = 2 + (b - r) / delta;
else if (b == v) h = 4 + (r - g) / delta;
}

return float3(h, s, v);
}

float3 hsv_to_rgb(float3 HSV)
{
float3 RGB = HSV.z;

float h = HSV.x;
float s = HSV.y;
float v = HSV.z;

float i = floor(h);
float f = h - i;

float p = (1.0 - s);
float q = (1.0 - s * f);
float t = (1.0 - s * (1 - f));

if (i == 0) { RGB = float3(1, t, p); }
else if (i == 1) { RGB = float3(q, 1, p); }
else if (i == 2) { RGB = float3(p, 1, t); }
else if (i == 3) { RGB = float3(p, q, 1); }
else if (i == 4) { RGB = float3(t, p, 1); }
else /* i == -1 */ { RGB = float3(1, p, q); }

RGB *= v;

return RGB;
}

float4 mainPS(float2 uv : TEXCOORD) : COLOR
{
float4 col = tex2D(Samp, uv);

float3 hsv = rgb_to_hsv(col.xyz);

hsv.x += Hue;
// Put the hue back to the -1 to 5 range
//if (hsv.x > 5) { hsv.x -= 6.0; }
hsv = hsv_to_rgb(hsv);
float4 newColor = float4(hsv,col.w);

float4 color = newColor;

color.rgb /= color.a;
color.rgb = color.rgb + Brightness;
color.rgb = ((color.rgb - 0.5f) * max(Contrast + 1.0, 0)) + 0.5f;
color.rgb *= color.a;

float greyscale = dot(color.rgb, float3(0.3, 0.59, 0.11));
color.rgb = lerp(greyscale, color.rgb, col.a * (Saturation + 1.0));
return color;
}

technique TransformTexture {
pass p0 {
}
}

Please If anyone can help me learning what am I doing wrong or any suggestions?
Any help will be of great value.

Tuesday, May 8, 2012 10:39 AM

• Why did you comment out this line?

//if (hsv.x > 5) { hsv.x -= 6.0; }

It seems that it is necessary to make sure hsv.x is on the range [-1,5] before calling hsv_to_rgb.

Hue is intended to work kind of like an angle, so [-1,5] is the same as [0,6].  or [-3,3].  If you scale it you can get degrees or radians or whatever.  Multiply h by 60 to get degrees, for example.  [-60,300]  Add 360 if h is negative, and that will make it on the range [0,360].  Or subtract 180 if h > 180 and that will put it on the range [-180,180]

In reality it is 3 [-1,+1] piece-wise intervals depending on whether R, G, or B is the maximal component: one centered on 0, one centered on 2 and one centered on 4.  (so one range from [-1,+1], one range from [+1,+3] and one range from [+3,+5].

• Marked as answer by Sunday, October 14, 2012 12:28 PM
Tuesday, May 8, 2012 5:31 PM