# RGB to HSV unintentionally hue shifting

I’m trying to write a simple shader to hue shift sprites by converting from RGB to HSV, adjusting hue, then shifting back. I’ve tried to adapt the formula’s found at this website (http://www.easyrgb.com/en/math.php) but when I convert from RGB to HSV then back without hue shifting I’m still getting the hue changed.
Here are the shader functions

``````float3 RGBtoHSV(in float3 rgb)
{
//R, G and B input range = 0 ÷ 255
//H, S and V output range = 0 ÷ 1.0
float H;
float S;
float V;

float R = (rgb[0] / 255);
float G = (rgb[1] / 255);
float B = (rgb[2] / 255);

float cMin = min(min(R, G), B);
float cMax = max(max(R, G), B);
float delta = cMax - cMin;

V = cMax;

if (cMax == 0)
{
H = 0;
S = 0;
}
else
{
S = delta / cMax;

float del_R = (((cMax - R) / 6) + (delta / 2)) / delta;
float del_G = (((cMax - G) / 6) + (delta / 2)) / delta;
float del_B = (((cMax - B) / 6) + (delta/ 2)) / delta;

if (R == cMax) H = del_B - del_G;
else if (G == cMax) H = (1 / 3) + del_R - del_B;
else if (B == cMax) H = (2 / 3) + del_G - del_R;

H = H % 1.0;
}

return float3(H, S, V);
}

float3 HSVtoRGB(in float3 hsv)
{
//H, S and V input range = 0 ÷ 1.0
//R, G and B output range = 0 ÷ 255
float H = hsv[0];
float S = hsv[1];
float V = hsv[2];

float R;
float G;
float B;

float var_r;
float var_g;
float var_b;

if (S == 0)
{
R = V * 255;
G = V * 255;
B = V * 255;
}
else
{
float var_h = H * 6;
if (var_h == 6) var_h = 0;     //H must be < 1
float var_i = floor(var_h);          //Or ... var_i = floor( var_h )
float var_1 = V * (1 - S);
float var_2 = V * (1 - S * (var_h - var_i));
float var_3 = V * (1 - S * (1 - (var_h - var_i)));

if (var_i == 0) { var_r = V; var_g = var_3; var_b = var_1; }
else if (var_i == 1) { var_r = var_2; var_g = V; var_b = var_1; }
else if (var_i == 2) { var_r = var_1; var_g = V; var_b = var_3; }
else if (var_i == 3) { var_r = var_1; var_g = var_2; var_b = V; }
else if (var_i == 4) { var_r = var_3; var_g = var_1; var_b = V; }
else { var_r = V; var_g = var_1; var_b = var_2; }

R = var_r * 255;
G = var_g * 255;
B = var_b * 255;
}

return float3(R, G, B);
}

float4 MainPS(VertexShaderOutput input) : COLOR
{
// get sprite color
float4 color = tex2D(s0, input.TextureCoordinates);
// Convert to HSV
float3 hsv = RGBtoHSV(float3(color.r, color.g, color.b));
// Convert back to RGB
float3 newColor = HSVtoRGB(hsv);
// Set new color
color = float4(newColor[0], newColor[1], newColor[2], color.a);
return color;
}
``````

The texture I’m passing in looks like this

And the image out I’m getting looks like this

When I compare the HSV values of the result vs the original image, it seems that saturation and value are both being computed correctly but the hue is off. For instance sampling 3 different pixels I found
(original → result): 0 → 60, 116 → 303, 336 → 60.
This relation doesn’t seem linear so I don’t think I can just do a simple adjustment in the code to fix it.

Does anybody have any ideas about what is going wrong here? Or some resources/existing shaders for RGB → HSV and back?

Hey out of curiosity, does the denominator type matter in HLSL like it does in C/C++?

For example, does that need to be…
`float del_R = (((cMax - R) / 6.0f) + (delta / 2.0f)) / delta;`

?

There’s some other places, but when numbers aren’t ending up where I expect them to be, sometimes errors like this are the culprit. I’m just not sure if HLSL works like this or not.