func gen_palette(hue: Color, shades: int) -> Array[Vector4]:
    var palette: Array[Vector4] = []

    # Convert palette hue to CIELAB
    var lab_hue = rgb_to_lab(hue.r, hue.g, hue.b)

    # Iterate over number of palette shades
    for i in range(0, shades + 1):  
        # Select RGB colors from the same a* and b* evenly spaced through luminance-space
        var shade = lab_to_rgb((i * (1/float(shades))) * 100., lab_hue.y, lab_hue.z)

        # Append color and luminance to shader buffer
        palette.append(Vector4(shade.x, shade.y, shade.z, i * (1/float(shades))))

    return palette

# Converts from linear RGB -> XYZ -> CIELAB per http://www.easyrgb.com/en/math.php
# CIE 1931 D65 XYZ references in use
func rgb_to_lab(r: float, g: float, b: float) -> Vector3:   
    r *= 100.
    g *= 100.
    b *= 100.

    var x = r * 0.4124 + g * 0.3576 + b * 0.1805
    var y = r * 0.2126 + g * 0.7152 + b * 0.0722
    var z = r * 0.0193 + g * 0.1192 + b * 0.9505

    x = x / 95.047
    y = y / 100.
    z = z / 108.883

    x = pow(x, 1./3.) if x > 0.008856 else (7.787 * x) + (16. / 116.)
    y = pow(y, 1./3.) if y > 0.008856 else (7.787 * y) + (16. / 116.)
    z = pow(z, 1./3.) if z > 0.008856 else (7.787 * z) + (16. / 116.)

    var lu = (116. * y) - 16.
    var al = 500. * (x - y)
    var be = 200. * (y - z)

    return Vector3(lu, al, be)

# Converts from CIELAB -> XYZ -> linear RGB per http://www.easyrgb.com/en/math.php
# CIE 1931 D65 XYZ references in use
func lab_to_rgb(l: float, a: float, b: float) -> Vector3:
    var y = (l + 16.) / 116.
    var x = a / 500. + y
    var z = y - b / 200.

    y = pow(y, 3.) if (pow(y, 3.) > 0.008856) else (y - 16. / 116.) / 7.787
    x = pow(x, 3.) if (pow(x, 3.) > 0.008856) else (x - 16. / 116.) / 7.787
    z = pow(z, 3.) if (pow(z, 3.) > 0.008856) else (z - 16. / 116.) / 7.787

    x *= 95.047
    y *= 100.
    z *= 108.883

    x /= 100.
    y /= 100.
    z /= 100.

    var re = x * 3.2406 + y * -1.5372 + z * -0.4986
    var gr = x * -0.9689 + y * 1.8758 + z * 0.0415
    var bl = x * 0.0557 + y * -0.204 + z * 1.057

    return Vector3(clamp(re, 0.0, 1.0), clamp(gr, 0.0, 1.0), clamp(bl, 0.0, 1.0))
Edit

Pub: 17 Nov 2024 01:53 UTC

Views: 7