How to convert HSV to RGB using shader nodes?

I am trying to implement the following function that converts HSV to RGB:

HSVtoRGB= function(color) {
var i;
var h,s,v,r,g,b;
h= color[0];
s= color[1];
v= color[2];
if(s === 0 ) {
// achromatic (grey)
r = g = b = v;
return [r,g,b];
}
h /= 60;            // sector 0 to 5
i = Math.floor( h );
f = h - i;          // factorial part of h
p = v * ( 1 - s );
q = v * ( 1 - s * f );
t = v * ( 1 - s * ( 1 - f ) );
switch( i ) {
case 0:
r = v;
g = t;
b = p;
break;
case 1:
r = q;
g = v;
b = p;
break;
case 2:
r = p;
g = v;
b = t;
break;
case 3:
r = p;
g = q;
b = v;
break;
case 4:
r = t;
g = p;
b = v;
break;
default:        // case 5:
r = v;
g = p;
b = q;
break;
}
return [r,g,b];
}


I'm completely fine up until the large switch/case structure. I have no idea how to implement this without creating a huge mess. It would be fine if each case was changing the same value, but each case has different variable assignments than others.

Here's my current nodegroup:

If someone could guide me to a working solution here, it would very much appreciated!

Is this an exercise, or ....

... will this do?...

EDIT: No, it won't. If you want to do logic like this by hand..

One way to approach the case statement would be use the implicit cast of True and False to 1 and 0, and multiply the truth-value of the case-condition with the color that would result if it were true.

.. so the above cluster says (v,t,p) * (i == 0) + (q,v,p) * (i == 1) +....

If the i == 0 condition is true, then the (v,t,p) contributes to the sum of colors. If the condition is false, it contributes (0,0,0). Only one case will be true, and contribute more than 0 to the sum.

You then accumulate a sum of all the colors:

But this stuff can be tedious to debug.. @Rich Sedman's kit can be a fantastic time-saver.

• Is your source H mapped from 0-360? Blender's H is 0-1, so you may have to divide your input H by 360. – Robin Betts Feb 20 at 10:01
• I should have clarified in my original post, but yes it's an exercise. I completely realize blender does this natively. I'm trying to get better at working with more complex node setups, as well as translating code to nodes. – Jay Feb 20 at 19:06
• @Jay Okydoky... I did think brockmann's edit of your title might not be quite right, this time.. I'm sure he wouldn't take offence if you put it back, and maybe clarified the Q so as to make the 'exercise' aspect a bit clearer. – Robin Betts Feb 20 at 19:13
• Thanks, no problemo, I'll edit it a bit later. – Jay Feb 20 at 19:17
• Very nicely explained. – Rich Sedman Feb 21 at 7:50

The code can be translated into a form that can be passed to the Node Expressions add-on to automatically build the node group. Paste the following text into a new text block named 'HSVtoRGB' and add the expression "TEXT:HSVtoRGB" to use it.

# Function to demonstrate converting HSV toRGB
#Inputs are Hue (0-360),Saturation(0-1), Value (0-1)

inputs(Color)
outputs(oColor)

h= Color[0]
s= Color[1]
v= Color[2]

h2 = h/60
i = floor( h2 )
f = h2 - i

p = v * ( 1 - s )
q = v * ( 1 - s * f )
t = v * ( 1 - s * ( 1 - f ) )

#Booleans based on value of i
i0 = (i==0)
i1 = (i==1)
i2 = (i==2)
i3 = (i==3)
i4 = (i==4)
i5 = not(or(i0,i1,i2,i3,i4))

#Combine products of booleans
r = (i0 * v) + (i1 * q) + (i2 * p) + (i3 * p) + (i4 * t) + (i5 * v)
g = (i0 * t) + (i1 * v) + (i2 * v) + (i3 * q) + (i4 * p) + (i5 * p)
b = (i0 * p) + (i1 * p) + (i2 * t) + (i3 * v) + (i4 * v) + (i5 * q)

oColor[] = combine(r,g,b)


The 'switch' statement is performed by first creating a number of boolean intermediate variables - in this case i0, i1, i2, i3, i4, i5 - by comparing with each of the cases. Note that i5 is calculated based on the other 5 variables since that should always be 1 whenever all of the others are blank (this will make it the 'otherwise' of the condition).

Each of these booleans is multiplied by the desired result in that case - and those products are simple added together to produce the final result. Provided only 1 of any of the booleans is ever 'true' (ie, 1) it is safe to combine via addition.

This produces the following node :

Containing the following :

The layout isn't particularly pretty but each 'sub-group' defines each of the variables in the expression text and can be reviewed individually if desired. Also, there's no need to edit the actual nodes since you can simply make any changes to the text and click 'Update' to refresh the nodes.