Game Development Community

Fun with color...

by Jason Cahill · in Torque Game Builder · 04/15/2006 (11:41 pm) · 3 replies

Hi everyone,

For my project I needed to be able to "tint" colors, based on existing colors. All of my sprites are pure white in the color channels and grayscale in the alpha channel. I then use .setBlendColor at runtime to color my sprites, based on player color or team color. I wanted the bullets from a given player object to be "of the same hue, but lighter and less saturated." So, here's the TorqueScript code to convert to and from RGBA (red-green-blue-alpha) to HLSA (hue-lightness-saturation-alpha):

function Color::RGBA2HLSA(%rgba)
{
   %r = getWord(%rgba, 0);
   %g = getWord(%rgba, 1);
   %b = getWord(%rgba, 2);
   %a = getWord(%rgba, 3);
   
   %max = ((%r > %g) ? ((%r > %b) ? %r : %b) : ((%g > %b) ? %g : %b));
   %min = ((%r < %g) ? ((%r < %b) ? %r : %b) : ((%g < %b) ? %g : %b));
   %l = (%max + %min) / 2;
   
   if (%max == %min)
   {
      %s = 0;
      %h = 0;
   }
   else
   {
      if (%l < 0.5) %s = (%max - %min) / (%max + %min);
      else %s = (%max - %min) / (2 - %max - %min);
      
      %delta = %max - %min;
      if (%r == %max) %h = (%g - %b) / %delta;
      else if (%g == %max) %h = 2 + (%b - %r) / %delta;
      else if (%b == %max) %h = 4 + (%r - %g) / %delta;
      
      %h *= 60;
      if (%h < 0) %h += 360;
   }
   return %h SPC %l SPC %s SPC %a;
}
 
function Color::Value(%n1, %n2, %h)
{
   while (%h > 360) %h -= 360;
   while (%h < 0) %h += 360;
   
   if (%h < 60) %v = %n1 + (%n2 - %n1) * %h / 60;
   else if (%h < 180) %v = %n2;
   else if (%h < 240) %v = %n1 + (%n2 - 1) * (240 - %h) / 60;
   else %v = %n1;
   
   return %v;
}
 
function Color::HLSA2RGBA(%hlsa)
{
   %h = getWord(%hlsa, 0);
   %l = getWord(%hlsa, 1);
   %s = getWord(%hlsa, 2);
   %a = getWord(%hlsa, 3);
   
   if (%l <= 0.5) %m2 = %l * (1 + %s);
   else %m2 = %l + %s - %l * %s;
   %m1 = 2 * %l - %m2;
   
   if (%s == 0)
   {
      if (%h == 0)
      {
         %r = %g = %b = %l;
      }
      else error("ERROR: HLSA2RGBA: hue must be 0 if saturation is 0!");
   }
   else
   {
      %r = Color::Value(%m1, %m2, %h + 120);
      %g = Color::Value(%m1, %m2, %h);
      %b = Color::Value(%m1, %m2, %h - 120);
   }
   
   return %r SPC %g SPC %b SPC %a;
}

#1
04/15/2006 (11:48 pm)
Color::RGBA2HLSA
Description: Converts an rgba value into a corresponding hlsa value.
Parameter: %rgba - a string containing red, green, blue, and alpha components (eg, "1 1 1 1" for pure white). r, g, b, and a are in the range [0, 1].
Result: %hlsa - a string containing hue, lightness, saturation, and alpha components (eg "0 1 0 1" for white). h in [0, 360], while l, s, and a are in the range [0, 1].

Color::HLSA2RGBA
Description: Converts an hlsa value into the corresponding rgba value.
Parameter: %hlsa - a string containing hue, lightness, saturation, and alpha components.
Result: %rgba - a string containing the red, green, blue, and alpha components.

This implementation is based on (and bug fixed) from Computer Graphics: Principles and Practice, Foley, van Dam, Feiner, Hughes, Second Edition, pages 595 - 596.
#2
04/15/2006 (11:51 pm)
Notes about HLS:
HLS is not HSV. HSV is a cone, where as HLS is a double cone. "Pure colors", like pure red, green, blue, yellow, etc exist at lightness = 0.5. White is up at lightness 1, while black is at lightness 0. Saturation is "grayest" at 0 and "most chromatic" at 1. Hue goes from 0 to 360. Red is at 0, Green at 120, Blue at 240.

Enjoy!
#3
04/17/2006 (11:01 am)
Nice functions! Thanks