Skip to content

Instantly share code, notes, and snippets.

@mrange
Last active May 16, 2021 19:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mrange/0e9e12e4f442d8e5d060b57a75646fac to your computer and use it in GitHub Desktop.
Save mrange/0e9e12e4f442d8e5d060b57a75646fac to your computer and use it in GitHub Desktop.
GLSL hsv2rgb macro for constexpr initialization

GLSL hsv2rgb macro for constexpr initialization

One piece of GLSL code I am constantly coming back to is Sam Hocevar's hsv2rbg and rgb2hsv functions posted on stackoverflow: https://stackoverflow.com/a/17897228/418488

The code

// Sam Hovevar has licensed the code under WTFPL.

// All components are in the range [0…1], including hue.
vec3 rgb2hsv(vec3 c)
{
    vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
    vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
    vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));

    float d = q.x - min(q.w, q.y);
    float e = 1.0e-10;
    return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}
// All components are in the range [0…1], including hue.
vec3 hsv2rgb(vec3 c)
{
    vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
    vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
    return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}

My small contribution

One thing I find myself wishing for is to initialize global const values from hsv2rbg but it doesn't work above because the const global values must be initialize from constexpr expressions

You can't declare a function constexpr in GLSL (yet) so I wrote this simple macro which is just hsv2rgb made into a macro

// License WTFPL
const vec4 hsv2rgb_K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
#define HSV2RGB(c)  (c.z * mix(hsv2rgb_K.xxx, clamp(abs(fract(c.xxx + hsv2rgb_K.xyz) * 6.0 - hsv2rgb_K.www) - hsv2rgb_K.xxx, 0.0, 1.0), c.y))

Example Usage

const vec3 grid_color   = HSV2RGB(vec3(0.6, 0.6, 1.0)); 
const vec3 plate_color  = HSV2RGB(vec3(0.0, 0.0, 0.125)); 
const vec3 plane_color  = HSV2RGB(vec3(0.7, 0.125, 1.0/32.0)); 

That's it.

Mårten

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment