## Saturday 3 October 2015

### RGB/HSV in HLSL 7

I got a very kind email from David Schaeffer yesterday with some bug fixes for the shader code I wrote for converting RGB to the HCY colour space.

My original implementation was

float3 RGBtoHCY(in float3 RGB)
{
float3 HCV = RGBtoHCV(RGB);
float Y = dot(RGB, HCYwts);
if (HCV.y != 0)
{
float Z = dot(HUEtoRGB(HCV.x), HCYwts);
if (Y > Z)
{
Y = 1 - Y;
Z = 1 - Z;
}
HCV.y *= Z / Y;
}
return float3(HCV.x, HCV.y, Y);
}

As he points out:
It seems to me that you have an error in your RGB to HCY code, though.  I was having some pixels always saturate to white, and after looking at Kuzma Shapran's original code I don't think the value of Y should actually be changed, only using the adjusted value of Y to calculate HCV.y.  Additionally I think the check for 0 in the original code was meant to prevent divide by 0 errors, so should be using Y instead of HCV.y.
I'll have to bow to David's superior knowledge on HCY usage as I've never actually used it in anger. So here's his improved version:

float3 RGBtoHCY(in float3 RGB)
{
float3 HCV = RGBtoHCV(RGB);
float Y = dot(RGB, HCYwts);
float Z = dot(HUEtoRGB(HCV.x), HCYwts);
if (Y < Z)
{
HCV.y *= Z / (Epsilon + Y);
}
else
{
HCV.y *= (1 - Z) / (Epsilon + 1 - Y);
}
return float3(HCV.x, HCV.y, Y);
}

I've updated the snippets page accordingly.