HSL shader (GLSL code)

Started by
-1 comments, last by MartijnKragtwijk 16 years, 7 months ago
Hi all, For anyone who's interested, I just adapted the fragment shader for HSL-based color adjustment posted by Delfi a year ago (http://www.gamedev.net/community/forums/topic.asp?topic_id=374703). I've made some corrections and improvements to it. Most importantly, the output now actually becomes greyscale when you turn down the saturation, the trick to make this work was to clamp the H, S and L values between 0 and 1 after adding the shifts and before converting back to RGB. I also 'repaired' the conditional returns in Hue_2_RGB(). Here's the code:

// with help of:
// JCL
// http://www.easyrgb.com/math.php?MATH=M19#text19
//
// 

//uniform sampler2D Texture1;

varying vec2 c; // texture coordinates from vertex shader
uniform sampler2D colorTex0;
uniform float AddHue;
uniform float AddSat;
uniform float AddLig;

float Hue_2_RGB(float v1, float v2, float vH )
{
	float ret;
   if ( vH < 0.0 )
     vH += 1.0;
   if ( vH > 1.0 )
     vH -= 1.0;
   if ( ( 6.0 * vH ) < 1.0 )
     ret = ( v1 + ( v2 - v1 ) * 6.0 * vH );
   else if ( ( 2.0 * vH ) < 1.0 )
     ret = ( v2 );
   else if ( ( 3.0 * vH ) < 2.0 )
     ret = ( v1 + ( v2 - v1 ) * ( ( 2.0 / 3.0 ) - vH ) * 6.0 );
   else
     ret = v1;
   return ret;
}

void main (void)
{
    vec4  color;

    float Cmax, Cmin;

    float D;
   
    float H, S, L;
    float R, G, B;

    // get fragment color
    color = texture2D(colorTex0, c);

    R = color.r;
    G = color.g;
    B = color.b;

// convert to HSL

    Cmax = max (R, max (G, B));
    Cmin = min (R, min (G, B));

// calculate lightness
    L = (Cmax + Cmin) / 2.0;

  if (Cmax == Cmin) // it's grey
  {
		H = 0.0; // it's actually undefined
		S = 0.0;
  }
  else
  {
    D = Cmax - Cmin; // we know D != 0 so we cas safely divide by it



// calculate Saturation
    if (L < 0.5)
    {
      S = D / (Cmax + Cmin);
    }
    else
    {
      S = D / (2.0 - (Cmax + Cmin));
    }

// calculate Hue
    if (R == Cmax)
    {
      H = (G - B) / D;
		} else {
      if (G == Cmax)
      {
      	 H = 2.0 + (B - R) /D;
      }
      else
      {
        H = 4.0 + (R - G) / D;
      }
   	}

    H = H / 6.0;


	}

// modify H/S/L values
H += AddHue;
S += AddSat;
L += AddLig;

if (H < 0.0)
{
	H = H + 1.0;
}

// clamp H,S and L to [0..1]

H = clamp(H, 0.0, 1.0);
S = clamp(S, 0.0, 1.0);
L = clamp(L, 0.0, 1.0);

// convert back to RGB

float var_2, var_1;

if (S == 0.0)
{
   R = L;
   G = L;
   B = L;
}
else
{
   if ( L < 0.5 )
   {
   var_2 = L * ( 1.0 + S );
   }
   else
   {
   var_2 = ( L + S ) - ( S * L );
   }

   var_1 = 2.0 * L - var_2;

   R = Hue_2_RGB( var_1, var_2, H + ( 1.0 / 3.0 ) );
   G = Hue_2_RGB( var_1, var_2, H );
   B = Hue_2_RGB( var_1, var_2, H - ( 1.0 / 3.0 ) );
}

 gl_FragColor = vec4(R,G,B, color.a);
	
}


This topic is closed to new replies.

Advertisement