none
Hue, saturation, brightness, contrast effect in hlsl RRS feed

  • 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 {
                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.
      Thanks In Advance.

                                                                                                                                                        
    Tuesday, May 8, 2012 10:39 AM

Answers

  • 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 Vibhore Tanwer Sunday, October 14, 2012 12:28 PM
    Tuesday, May 8, 2012 5:31 PM