0 votes

As the title suggests, I'm looking for a way to use the hsv values of a color instead of the rgb values, I tried to look for some answers and came across a couple of functions that didn't work very well for me.

if anyone got a working converters and could share them with me it would be lovely.

in Engine by (1,193 points)

if anyone got a working converters and could share them with me it would be lovely.

If you're a command-line fan, pastel should work well for you :)

1 Answer

0 votes
Best answer

I need HSV to RGB conversion for a project of mine, so I wrote a quick dirty function. It's not a whole converter suite or anything, but I thought I'd share it in case it saves somebody some work.
I've included an example where you get the usual color wheel if you put the shader on a square.

shader_type canvas_item;
const float PI = 3.14159265358979323846;

vec4 hsv_to_rgb(float h, float s, float v, float a){
    //based on 
    // So it needs values from 0 to 1
    float r;
    float g;
    float b;

    float i = floor(h*6.0);
    float f = h*6.0 -i;
    float p = v*(1.0-s);
    float q = v*(1.0-f*s);
    float t = v* (1.0-(1.0-f)*s);

    int cond = int(i)%6;

    if (cond == 0){
        r = v; g = t; b = p;
    else if (cond == 1){
        r = q; g = v; b = p;
    else if (cond == 2){
        r = p; g = v; b = t;
    else if (cond == 3){
        r = p; g = q; b = v;
    else if (cond == 4){
        r = t; g = p; b = v;
    else if (cond == 5){
        r = v; g = p; b = q;
    else {
        r = 0.0; g = 0.0; b = 0.0;
    return vec4(r,g,b,a);

    return vec4(0.5,1.0,0.0,1.0);

float atan2(float x, float y){
    if (x > 0.0){
        return atan(y/x);
    else if (x < 0.0){
        if (y >= 0.0){
            return atan(y/x) + PI;
        else {
            return atan(y/x) - PI;
    else { // This is x=0
        if(y > 0.0){
            return PI/2.0;
        else {
            // This includes the actually undefined x=y=0 case
            return -PI/2.0;

vec2 cartesian_to_polar(vec2 XY){
    float r = length(XY);
    float phi = (atan2(XY[0],XY[1]) + PI)/(2.0*PI);
    // We shift the atan2 to the [0,2pi] range and then normalize
    return vec2(r,phi);

void fragment(){
    // Center coordinates
    vec2 XY = 2.0*UV - 1.0;
    vec2 RPhi = cartesian_to_polar(XY);
    float r = RPhi[0];
    float phi = RPhi[1];
    COLOR = hsv_to_rgb(phi,r/sqrt(2.0),1.0,1.0);

edit: (We need to normalize r, so I added r/sqrt(2.0) because otherwise r is not between 0 and 1)

by (44 points)
edited by
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.