Hue, saturation, brightness, contrast effect in hlsl
- by Vibhore Tanwer
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 colorWithBrightnessAndContrast = newColor;
colorWithBrightnessAndContrast.rgb /= colorWithBrightnessAndContrast.a;
colorWithBrightnessAndContrast.rgb = colorWithBrightnessAndContrast.rgb + Brightness;
colorWithBrightnessAndContrast.rgb = ((colorWithBrightnessAndContrast.rgb - 0.5f) * max(Contrast + 1.0, 0)) + 0.5f;
colorWithBrightnessAndContrast.rgb *= colorWithBrightnessAndContrast.a;
float greyscale = dot(colorWithBrightnessAndContrast.rgb, float3(0.3, 0.59, 0.11));
colorWithBrightnessAndContrast.rgb = lerp(greyscale, colorWithBrightnessAndContrast.rgb, col.a * (Saturation + 1.0));
return colorWithBrightnessAndContrast;
}
technique TransformTexture {
pass p0 {
PixelShader = compile ps_2_0 mainPS();
}
}
Please If anyone can help me learning what am I doing wrong or any suggestions?
Any help will be of great value.
EDIT:
Images of the effect at hue 180:
On the left hand side, the effect I got with @teodron answer. On the right hand side, The effect Paint.NET gives and I'm trying to reproduce.