LYGIA Shader Library

rgb2ryb (lygia/color/space/rgb2ryb)

Converts a color from RGB to RYB color space. Based on http://nishitalab.org/user/UEI/publication/Sugita_IWAIT2015.pdf and https://bahamas10.github.io/ryb/assets/ryb.pdf

Dependencies:

Use:

<vec3|vec4> ryb2rgb(<vec3|vec4> ryb)

Check it on Github



#ifndef RYB_LERP 
#define RYB_LERP(A, B, t) cubicMix(A, B, t)
#endif

#ifndef FNC_RGB2RYB
#define FNC_RGB2RYB

#ifdef RYB_FAST

vec3 rgb2ryb(vec3 rgb) {
    // Remove the white from the color
    float w = mmin(rgb);
    float bl = mmin(1.0 - rgb);
    rgb -= w;

    float max_g = mmax(rgb);

    // Get the yellow out of the red & green
    float y = mmin(rgb.rg);
    vec3 ryb = rgb - vec3(y, y, 0.);

    // If this unfortunate conversion combines blue and green, then cut each in half to preserve the value's maximum range.
    if (ryb.b > 0. && ryb.y > 0.) {
        ryb.b *= .5;
        ryb.y *= .5;
    }

    // Redistribute the remaining green.
    ryb.b += ryb.y;
    ryb.y += y;

    // Normalize to values.
    float max_y = mmax(ryb);
    ryb *= (max_y > 0.) ? max_g / max_y : 1.;

    // Add the white back in.
#ifdef RYB_FAST
    return ryb + w;
#else
    return ryb + bl;
#endif
}

#else

vec3 rgb2ryb(vec3 rgb) {
    const vec3 rgb000 = vec3(1., 1., 1.);       // Black
    const vec3 rgb100 = vec3(1., 0., 0.);       // Red          
    const vec3 rgb010 = vec3(0., 1., .483);     // Green
    const vec3 rgb110 = vec3(0., 1., 0.);       // Yellow
    const vec3 rgb001 = vec3(0., 0., 1.);       // Blue
    const vec3 rgb101 = vec3(.309, 0., .469);   // Magenta
    const vec3 rgb011 = vec3(0., .053, .210);   // Turquoise
    const vec3 rgb111 = vec3(0., 0., 0.);       // White
    return RYB_LERP(RYB_LERP(
        RYB_LERP(rgb000, rgb001, rgb.z),
        RYB_LERP(rgb010, rgb011, rgb.z),
        rgb.y), RYB_LERP(
        RYB_LERP(rgb100, rgb101, rgb.z),
        RYB_LERP(rgb110, rgb111, rgb.z),
        rgb.y), rgb.x);
}

#endif

vec4 rgb2ryb(vec4 rgb) { return vec4(rgb2ryb(rgb.rgb), rgb.a); }

#endif

Dependencies:

Use:

<float3|float4> ryb2rgb(<float3|float4> ryb)

Check it on Github



#ifndef RYB_LERP 
#define RYB_LERP(A, B, t) cubicMix(A, B, t)
#endif

#ifndef FNC_RGB2RYB
#define FNC_RGB2RYB

#ifdef RYB_FAST

float3 rgb2ryb(float3 rgb) {
    // Remove the white from the color
    float w = mmin(rgb);
    float bl = mmin(1.0 - rgb);
    rgb -= w;

    float max_g = mmax(rgb);

    // Get the yellow out of the red & green
    float y = mmin(rgb.rg);
    float3 ryb = rgb - float3(y, y, 0.);

    // If this unfortunate conversion combines blue and green, then cut each in half to preserve the value's maximum range.
    if (ryb.b > 0. && ryb.y > 0.) {
        ryb.b *= .5;
        ryb.y *= .5;
    }

    // Redistribute the remaining green.
    ryb.b += ryb.y;
    ryb.y += y;

    // Normalize to values.
    float max_y = mmax(ryb);
    ryb *= (max_y > 0.) ? max_g / max_y : 1.;

    // Add the white back in.
#ifdef RYB_FAST
    return ryb + w;
#else
    return ryb + bl;
#endif
}

#else

float3 rgb2ryb(float3 rgb) {
    const float3 rgb000 = float3(1., 1., 1.);       // Black
    const float3 rgb100 = float3(1., 0., 0.);       // Red          
    const float3 rgb010 = float3(0., 1., .483);     // Green
    const float3 rgb110 = float3(0., 1., 0.);       // Yellow
    const float3 rgb001 = float3(0., 0., 1.);       // Blue
    const float3 rgb101 = float3(.309, 0., .469);   // Magenta
    const float3 rgb011 = float3(0., .053, .210);   // Turquoise
    const float3 rgb111 = float3(0., 0., 0.);       // White
    return RYB_LERP(RYB_LERP(
        RYB_LERP(rgb000, rgb001, rgb.z),
        RYB_LERP(rgb010, rgb011, rgb.z),
        rgb.y), RYB_LERP(
        RYB_LERP(rgb100, rgb101, rgb.z),
        RYB_LERP(rgb110, rgb111, rgb.z),
        rgb.y), rgb.x);
}

#endif

float4 rgb2ryb(float4 rgb) { return float4(rgb2ryb(rgb.rgb), rgb.a); }

#endif

Dependencies:

Use:

<float3|float4> ryb2rgb(<float3|float4> ryb)

Check it on Github



#ifndef RYB_LERP 
#define RYB_LERP(A, B, t) cubicMix(A, B, t)
#endif

#ifndef FNC_RGB2RYB
#define FNC_RGB2RYB

#ifdef RYB_FAST

float3 rgb2ryb(float3 rgb) {
    // Remove the white from the color
    float w = mmin(rgb);
    float bl = mmin(1.0 - rgb);
    rgb -= w;

    float max_g = mmax(rgb);

    // Get the yellow out of the red & green
    float y = mmin(rgb.rg);
    float3 ryb = rgb - float3(y, y, 0.);

    // If this unfortunate conversion combines blue and green, then cut each half to preserve the value's maximum range.
    if (ryb.b > 0. && ryb.y > 0.) {
        ryb.b *= .5;
        ryb.y *= .5;
    }

    // Redistribute the remaining green.
    ryb.b += ryb.y;
    ryb.y += y;

    // Normalize to values.
    float max_y = mmax(ryb);
    ryb *= (max_y > 0.) ? max_g / max_y : 1.;

    // Add the white back in.
#ifdef RYB_FAST
    return ryb + w;
#else
    return ryb + bl;
#endif
}

#else

float3 rgb2ryb(float3 rgb) {
    constant float3 rgb000 = float3(1., 1., 1.);       // Black
    constant float3 rgb100 = float3(1., 0., 0.);       // Red          
    constant float3 rgb010 = float3(0., 1., .483);     // Green
    constant float3 rgb110 = float3(0., 1., 0.);       // Yellow
    constant float3 rgb001 = float3(0., 0., 1.);       // Blue
    constant float3 rgb101 = float3(.309, 0., .469);   // Magenta
    constant float3 rgb011 = float3(0., .053, .210);   // Turquoise
    constant float3 rgb111 = float3(0., 0., 0.);       // White
    return RYB_LERP(RYB_LERP(
        RYB_LERP(rgb000, rgb001, rgb.z),
        RYB_LERP(rgb010, rgb011, rgb.z),
        rgb.y), RYB_LERP(
        RYB_LERP(rgb100, rgb101, rgb.z),
        RYB_LERP(rgb110, rgb111, rgb.z),
        rgb.y), rgb.x);
}

#endif

float4 rgb2ryb(float4 rgb) { return float4(rgb2ryb(rgb.rgb), rgb.a); }

#endif

Dependencies:

Use:

<vec3f> ryb2rgb(<vec3f> ryb)

Check it on Github



fn rgb2ryb(rgb: vec3f) -> vec3f {
    let rgb000 = vec3f(1., 1., 1.);       // Black
    let rgb100 = vec3f(1., 0., 0.);       // Red          
    let rgb010 = vec3f(0., 1., .483);     // Green
    let rgb110 = vec3f(0., 1., 0.);       // Yellow
    let rgb001 = vec3f(0., 0., 1.);       // Blue
    let rgb101 = vec3f(.309, 0., .469);   // Magenta
    let rgb011 = vec3f(0., .053, .210);   // Turquoise
    let rgb111 = vec3f(0., 0., 0.);       // White
    return cubeMix3(cubeMix3(
        cubeMix3(rgb000, rgb001, rgb.z),
        cubeMix3(rgb010, rgb011, rgb.z),
        rgb.y), cubeMix3(
        cubeMix3(rgb100, rgb101, rgb.z),
        cubeMix3(rgb110, rgb111, rgb.z),
        rgb.y), rgb.x);
}

Examples

Licenses

LYGIA is dual-licensed under the Prosperity License and the Patron License for sponsors and contributors.

Sponsors and contributors are automatically added to the Patron License and they can ignore the any non-commercial rule of the Prosperity Licensed software (please take a look to the exception).

It's also possible to get a permanent comercial license hook to a single and specific version of LYGIA.

Get the latest news and releases

Sign up for the news letter bellow, joing the LYGIA's channel on Discord or follow the Github repository