6
$\begingroup$

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:

Nodes

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

$\endgroup$
1
7
$\begingroup$

Is this an exercise, or ....

enter image description here

... 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.

enter image description here

.. 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:

enter image description here

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

$\endgroup$
5
  • 2
    $\begingroup$ 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. $\endgroup$ – Robin Betts Feb 20 at 10:01
  • $\begingroup$ 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. $\endgroup$ – Jay Feb 20 at 19:06
  • $\begingroup$ @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. $\endgroup$ – Robin Betts Feb 20 at 19:13
  • $\begingroup$ Thanks, no problemo, I'll edit it a bit later. $\endgroup$ – Jay Feb 20 at 19:17
  • $\begingroup$ Very nicely explained. $\endgroup$ – Rich Sedman Feb 21 at 7:50
4
$\begingroup$

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 :

node external

Containing the following :

node internal

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.

Note that the add-on can be downloaded from https://github.com/baldingwizard/Blender-Addons/wiki/Dynamic-Maths-Expression

Blend file included for completeness

$\endgroup$
4
  • $\begingroup$ Phew! I felt I had to debug my spaghetti before posting, and there's a slip somewhere, even though the principle is OK.. $\endgroup$ – Robin Betts Feb 20 at 22:25
  • $\begingroup$ @RobinBetts Debugging nodes is sometimes such a pain, isn’t it. One wrong link or a ‘Clamp’ accidentally clicked and you’re left hunting around for ages trying to find the problem. $\endgroup$ – Rich Sedman Feb 21 at 7:42
  • $\begingroup$ @RichSedman Thank you so much for detailing your process. Do you have any idea how I could hook up an image texture to the input such that I can use the sliders for HSV adjustment? Do I also need an RGB to HSV node group? I know this is a little outside the scope of my original question, sorry about that. $\endgroup$ – Jay Feb 21 at 20:38
  • $\begingroup$ @Jay Glad to help. Yes - I think you would need to convert from image RGB to HSV, then manipulate the HSV values (by adding/subtracting, etc - the “sliders” you mention) then use the HSV to RGB to get back to RGB to output as the final image result. If you have the code to RGB to HSV you could do similar to that described above to create a node group to do that. $\endgroup$ – Rich Sedman Feb 21 at 22:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.