palette-shader 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"palette-shader.umd.cjs","sources":["../src/shaders/srgb2rgb.frag.glsl?raw","../src/shaders/oklab.frag.glsl?raw","../src/shaders/hsl2rgb.frag.glsl?raw","../src/shaders/hsv2rgb.frag.glsl?raw","../src/shaders/lch2rgb.frag.glsl?raw","../src/shaders/deltaE.frag.glsl?raw","../src/shaders/closestColor.frag.glsl?raw","../src/index.ts"],"sourcesContent":["export default \"// https://lygia.xyz/\\nfloat srgb2rgb(const in float v) { return (v < 0.04045) ? v * 0.0773993808 : pow((v + 0.055) * 0.947867298578199, 2.4); }\\nvec3 srgb2rgb(const in vec3 srgb) { return vec3(srgb2rgb(srgb.r), srgb2rgb(srgb.g), srgb2rgb(srgb.b)); }\\nvec4 srgb2rgb(const in vec4 srgb) { return vec4(srgb2rgb(srgb.rgb), srgb.a); }\\n\"","export default \"// Copyright(c) 2021 Björn Ottosson\\n//\\n// Permission is hereby granted, free of charge, to any person obtaining a copy of\\n// this softwareand associated documentation files(the \\\"Software\\\"), to deal in\\n// the Software without restriction, including without limitation the rights to\\n// use, copy, modify, merge, publish, distribute, sublicense, and /or sell copies\\n// of the Software, and to permit persons to whom the Software is furnished to do\\n// so, subject to the following conditions :\\n// The above copyright noticeand this permission notice shall be included in all\\n// copies or substantial portions of the Software.\\n// THE SOFTWARE IS PROVIDED \\\"AS IS\\\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE\\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\\n// SOFTWARE.\\n\\n#define M_PI 3.1415926535897932384626433832795\\n\\nfloat cbrt( float x )\\n{\\n return sign(x)*pow(abs(x),1.0f/3.0f);\\n}\\n\\nfloat srgb_transfer_function(float a)\\n{\\n\\treturn .0031308f >= a ? 12.92f * a : 1.055f * pow(a, .4166666666666667f) - .055f;\\n}\\n\\nfloat srgb_transfer_function_inv(float a)\\n{\\n\\treturn .04045f < a ? pow((a + .055f) / 1.055f, 2.4f) : a / 12.92f;\\n}\\n\\nvec3 linear_srgb_to_oklab(vec3 c)\\n{\\n\\tfloat l = 0.4122214708f * c.r + 0.5363325363f * c.g + 0.0514459929f * c.b;\\n\\tfloat m = 0.2119034982f * c.r + 0.6806995451f * c.g + 0.1073969566f * c.b;\\n\\tfloat s = 0.0883024619f * c.r + 0.2817188376f * c.g + 0.6299787005f * c.b;\\n\\n\\tfloat l_ = cbrt(l);\\n\\tfloat m_ = cbrt(m);\\n\\tfloat s_ = cbrt(s);\\n\\n\\treturn vec3(\\n\\t\\t0.2104542553f * l_ + 0.7936177850f * m_ - 0.0040720468f * s_,\\n\\t\\t1.9779984951f * l_ - 2.4285922050f * m_ + 0.4505937099f * s_,\\n\\t\\t0.0259040371f * l_ + 0.7827717662f * m_ - 0.8086757660f * s_\\n\\t);\\n}\\n\\nvec3 oklab_to_linear_srgb(vec3 c)\\n{\\n\\tfloat l_ = c.x + 0.3963377774f * c.y + 0.2158037573f * c.z;\\n\\tfloat m_ = c.x - 0.1055613458f * c.y - 0.0638541728f * c.z;\\n\\tfloat s_ = c.x - 0.0894841775f * c.y - 1.2914855480f * c.z;\\n\\n\\tfloat l = l_ * l_ * l_;\\n\\tfloat m = m_ * m_ * m_;\\n\\tfloat s = s_ * s_ * s_;\\n\\n\\treturn vec3(\\n\\t\\t+4.0767416621f * l - 3.3077115913f * m + 0.2309699292f * s,\\n\\t\\t-1.2684380046f * l + 2.6097574011f * m - 0.3413193965f * s,\\n\\t\\t-0.0041960863f * l - 0.7034186147f * m + 1.7076147010f * s\\n\\t);\\n}\\n\\n// Finds the maximum saturation possible for a given hue that fits in sRGB\\n// Saturation here is defined as S = C/L\\n// a and b must be normalized so a^2 + b^2 == 1\\nfloat compute_max_saturation(float a, float b)\\n{\\n\\t// Max saturation will be when one of r, g or b goes below zero.\\n\\n\\t// Select different coefficients depending on which component goes below zero first\\n\\tfloat k0, k1, k2, k3, k4, wl, wm, ws;\\n\\n\\tif (-1.88170328f * a - 0.80936493f * b > 1.f)\\n\\t{\\n\\t\\t// Red component\\n\\t\\tk0 = +1.19086277f; k1 = +1.76576728f; k2 = +0.59662641f; k3 = +0.75515197f; k4 = +0.56771245f;\\n\\t\\twl = +4.0767416621f; wm = -3.3077115913f; ws = +0.2309699292f;\\n\\t}\\n\\telse if (1.81444104f * a - 1.19445276f * b > 1.f)\\n\\t{\\n\\t\\t// Green component\\n\\t\\tk0 = +0.73956515f; k1 = -0.45954404f; k2 = +0.08285427f; k3 = +0.12541070f; k4 = +0.14503204f;\\n\\t\\twl = -1.2684380046f; wm = +2.6097574011f; ws = -0.3413193965f;\\n\\t}\\n\\telse\\n\\t{\\n\\t\\t// Blue component\\n\\t\\tk0 = +1.35733652f; k1 = -0.00915799f; k2 = -1.15130210f; k3 = -0.50559606f; k4 = +0.00692167f;\\n\\t\\twl = -0.0041960863f; wm = -0.7034186147f; ws = +1.7076147010f;\\n\\t}\\n\\n\\t// Approximate max saturation using a polynomial:\\n\\tfloat S = k0 + k1 * a + k2 * b + k3 * a * a + k4 * a * b;\\n\\n\\t// Do one step Halley's method to get closer\\n\\t// this gives an error less than 10e6, except for some blue hues where the dS/dh is close to infinite\\n\\t// this should be sufficient for most applications, otherwise do two/three steps \\n\\n\\tfloat k_l = +0.3963377774f * a + 0.2158037573f * b;\\n\\tfloat k_m = -0.1055613458f * a - 0.0638541728f * b;\\n\\tfloat k_s = -0.0894841775f * a - 1.2914855480f * b;\\n\\n\\t{\\n\\t\\tfloat l_ = 1.f + S * k_l;\\n\\t\\tfloat m_ = 1.f + S * k_m;\\n\\t\\tfloat s_ = 1.f + S * k_s;\\n\\n\\t\\tfloat l = l_ * l_ * l_;\\n\\t\\tfloat m = m_ * m_ * m_;\\n\\t\\tfloat s = s_ * s_ * s_;\\n\\n\\t\\tfloat l_dS = 3.f * k_l * l_ * l_;\\n\\t\\tfloat m_dS = 3.f * k_m * m_ * m_;\\n\\t\\tfloat s_dS = 3.f * k_s * s_ * s_;\\n\\n\\t\\tfloat l_dS2 = 6.f * k_l * k_l * l_;\\n\\t\\tfloat m_dS2 = 6.f * k_m * k_m * m_;\\n\\t\\tfloat s_dS2 = 6.f * k_s * k_s * s_;\\n\\n\\t\\tfloat f = wl * l + wm * m + ws * s;\\n\\t\\tfloat f1 = wl * l_dS + wm * m_dS + ws * s_dS;\\n\\t\\tfloat f2 = wl * l_dS2 + wm * m_dS2 + ws * s_dS2;\\n\\n\\t\\tS = S - f * f1 / (f1 * f1 - 0.5f * f * f2);\\n\\t}\\n\\n\\treturn S;\\n}\\n\\n// finds L_cusp and C_cusp for a given hue\\n// a and b must be normalized so a^2 + b^2 == 1\\nvec2 find_cusp(float a, float b)\\n{\\n\\t// First, find the maximum saturation (saturation S = C/L)\\n\\tfloat S_cusp = compute_max_saturation(a, b);\\n\\n\\t// Convert to linear sRGB to find the first point where at least one of r,g or b >= 1:\\n\\tvec3 rgb_at_max = oklab_to_linear_srgb(vec3( 1, S_cusp * a, S_cusp * b ));\\n\\tfloat L_cusp = cbrt(1.f / max(max(rgb_at_max.r, rgb_at_max.g), rgb_at_max.b));\\n\\tfloat C_cusp = L_cusp * S_cusp;\\n\\n\\treturn vec2( L_cusp , C_cusp );\\n}\\n\\n// Finds intersection of the line defined by \\n// L = L0 * (1 - t) + t * L1;\\n// C = t * C1;\\n// a and b must be normalized so a^2 + b^2 == 1\\nfloat find_gamut_intersection(float a, float b, float L1, float C1, float L0, vec2 cusp)\\n{\\n\\t// Find the intersection for upper and lower half seprately\\n\\tfloat t;\\n\\tif (((L1 - L0) * cusp.y - (cusp.x - L0) * C1) <= 0.f)\\n\\t{\\n\\t\\t// Lower half\\n\\n\\t\\tt = cusp.y * L0 / (C1 * cusp.x + cusp.y * (L0 - L1));\\n\\t}\\n\\telse\\n\\t{\\n\\t\\t// Upper half\\n\\n\\t\\t// First intersect with triangle\\n\\t\\tt = cusp.y * (L0 - 1.f) / (C1 * (cusp.x - 1.f) + cusp.y * (L0 - L1));\\n\\n\\t\\t// Then one step Halley's method\\n\\t\\t{\\n\\t\\t\\tfloat dL = L1 - L0;\\n\\t\\t\\tfloat dC = C1;\\n\\n\\t\\t\\tfloat k_l = +0.3963377774f * a + 0.2158037573f * b;\\n\\t\\t\\tfloat k_m = -0.1055613458f * a - 0.0638541728f * b;\\n\\t\\t\\tfloat k_s = -0.0894841775f * a - 1.2914855480f * b;\\n\\n\\t\\t\\tfloat l_dt = dL + dC * k_l;\\n\\t\\t\\tfloat m_dt = dL + dC * k_m;\\n\\t\\t\\tfloat s_dt = dL + dC * k_s;\\n\\n\\n\\t\\t\\t// If higher accuracy is required, 2 or 3 iterations of the following block can be used:\\n\\t\\t\\t{\\n\\t\\t\\t\\tfloat L = L0 * (1.f - t) + t * L1;\\n\\t\\t\\t\\tfloat C = t * C1;\\n\\n\\t\\t\\t\\tfloat l_ = L + C * k_l;\\n\\t\\t\\t\\tfloat m_ = L + C * k_m;\\n\\t\\t\\t\\tfloat s_ = L + C * k_s;\\n\\n\\t\\t\\t\\tfloat l = l_ * l_ * l_;\\n\\t\\t\\t\\tfloat m = m_ * m_ * m_;\\n\\t\\t\\t\\tfloat s = s_ * s_ * s_;\\n\\n\\t\\t\\t\\tfloat ldt = 3.f * l_dt * l_ * l_;\\n\\t\\t\\t\\tfloat mdt = 3.f * m_dt * m_ * m_;\\n\\t\\t\\t\\tfloat sdt = 3.f * s_dt * s_ * s_;\\n\\n\\t\\t\\t\\tfloat ldt2 = 6.f * l_dt * l_dt * l_;\\n\\t\\t\\t\\tfloat mdt2 = 6.f * m_dt * m_dt * m_;\\n\\t\\t\\t\\tfloat sdt2 = 6.f * s_dt * s_dt * s_;\\n\\n\\t\\t\\t\\tfloat r = 4.0767416621f * l - 3.3077115913f * m + 0.2309699292f * s - 1.f;\\n\\t\\t\\t\\tfloat r1 = 4.0767416621f * ldt - 3.3077115913f * mdt + 0.2309699292f * sdt;\\n\\t\\t\\t\\tfloat r2 = 4.0767416621f * ldt2 - 3.3077115913f * mdt2 + 0.2309699292f * sdt2;\\n\\n\\t\\t\\t\\tfloat u_r = r1 / (r1 * r1 - 0.5f * r * r2);\\n\\t\\t\\t\\tfloat t_r = -r * u_r;\\n\\n\\t\\t\\t\\tfloat g = -1.2684380046f * l + 2.6097574011f * m - 0.3413193965f * s - 1.f;\\n\\t\\t\\t\\tfloat g1 = -1.2684380046f * ldt + 2.6097574011f * mdt - 0.3413193965f * sdt;\\n\\t\\t\\t\\tfloat g2 = -1.2684380046f * ldt2 + 2.6097574011f * mdt2 - 0.3413193965f * sdt2;\\n\\n\\t\\t\\t\\tfloat u_g = g1 / (g1 * g1 - 0.5f * g * g2);\\n\\t\\t\\t\\tfloat t_g = -g * u_g;\\n\\n\\t\\t\\t\\tfloat b = -0.0041960863f * l - 0.7034186147f * m + 1.7076147010f * s - 1.f;\\n\\t\\t\\t\\tfloat b1 = -0.0041960863f * ldt - 0.7034186147f * mdt + 1.7076147010f * sdt;\\n\\t\\t\\t\\tfloat b2 = -0.0041960863f * ldt2 - 0.7034186147f * mdt2 + 1.7076147010f * sdt2;\\n\\n\\t\\t\\t\\tfloat u_b = b1 / (b1 * b1 - 0.5f * b * b2);\\n\\t\\t\\t\\tfloat t_b = -b * u_b;\\n\\n\\t\\t\\t\\tt_r = u_r >= 0.f ? t_r : 10000.f;\\n\\t\\t\\t\\tt_g = u_g >= 0.f ? t_g : 10000.f;\\n\\t\\t\\t\\tt_b = u_b >= 0.f ? t_b : 10000.f;\\n\\n\\t\\t\\t\\tt += min(t_r, min(t_g, t_b));\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\n\\treturn t;\\n}\\n\\nfloat find_gamut_intersection(float a, float b, float L1, float C1, float L0)\\n{\\n\\t// Find the cusp of the gamut triangle\\n\\tvec2 cusp = find_cusp(a, b);\\n\\n\\treturn find_gamut_intersection(a, b, L1, C1, L0, cusp);\\n}\\n\\nvec3 gamut_clip_preserve_chroma(vec3 rgb)\\n{\\n\\tif (rgb.r < 1.f && rgb.g < 1.f && rgb.b < 1.f && rgb.r > 0.f && rgb.g > 0.f && rgb.b > 0.f)\\n\\t\\treturn rgb;\\n\\n\\tvec3 lab = linear_srgb_to_oklab(rgb);\\n\\n\\tfloat L = lab.x;\\n\\tfloat eps = 0.00001f;\\n\\tfloat C = max(eps, sqrt(lab.y * lab.y + lab.z * lab.z));\\n\\tfloat a_ = lab.y / C;\\n\\tfloat b_ = lab.z / C;\\n\\n\\tfloat L0 = clamp(L, 0.f, 1.f);\\n\\n\\tfloat t = find_gamut_intersection(a_, b_, L, C, L0);\\n\\tfloat L_clipped = L0 * (1.f - t) + t * L;\\n\\tfloat C_clipped = t * C;\\n\\n\\treturn oklab_to_linear_srgb(vec3( L_clipped, C_clipped * a_, C_clipped * b_ ));\\n}\\n\\nvec3 gamut_clip_project_to_0_5(vec3 rgb)\\n{\\n\\tif (rgb.r < 1.f && rgb.g < 1.f && rgb.b < 1.f && rgb.r > 0.f && rgb.g > 0.f && rgb.b > 0.f)\\n\\t\\treturn rgb;\\n\\n\\tvec3 lab = linear_srgb_to_oklab(rgb);\\n\\n\\tfloat L = lab.x;\\n\\tfloat eps = 0.00001f;\\n\\tfloat C = max(eps, sqrt(lab.y * lab.y + lab.z * lab.z));\\n\\tfloat a_ = lab.y / C;\\n\\tfloat b_ = lab.z / C;\\n\\n\\tfloat L0 = 0.5;\\n\\n\\tfloat t = find_gamut_intersection(a_, b_, L, C, L0);\\n\\tfloat L_clipped = L0 * (1.f - t) + t * L;\\n\\tfloat C_clipped = t * C;\\n\\n\\treturn oklab_to_linear_srgb(vec3( L_clipped, C_clipped * a_, C_clipped * b_ ));\\n}\\n\\nvec3 gamut_clip_project_to_L_cusp(vec3 rgb)\\n{\\n\\tif (rgb.r < 1.f && rgb.g < 1.f && rgb.b < 1.f && rgb.r > 0.f && rgb.g > 0.f && rgb.b > 0.f)\\n\\t\\treturn rgb;\\n\\n\\tvec3 lab = linear_srgb_to_oklab(rgb);\\n\\n\\tfloat L = lab.x;\\n\\tfloat eps = 0.00001f;\\n\\tfloat C = max(eps, sqrt(lab.y * lab.y + lab.z * lab.z));\\n\\tfloat a_ = lab.y / C;\\n\\tfloat b_ = lab.z / C;\\n\\n\\t// The cusp is computed here and in find_gamut_intersection, an optimized solution would only compute it once.\\n\\tvec2 cusp = find_cusp(a_, b_);\\n\\n\\tfloat L0 = cusp.x;\\n\\n\\tfloat t = find_gamut_intersection(a_, b_, L, C, L0);\\n\\n\\tfloat L_clipped = L0 * (1.f - t) + t * L;\\n\\tfloat C_clipped = t * C;\\n\\n\\treturn oklab_to_linear_srgb(vec3( L_clipped, C_clipped * a_, C_clipped * b_ ));\\n}\\n\\nvec3 gamut_clip_adaptive_L0_0_5(vec3 rgb, float alpha)\\n{\\n\\tif (rgb.r < 1.f && rgb.g < 1.f && rgb.b < 1.f && rgb.r > 0.f && rgb.g > 0.f && rgb.b > 0.f)\\n\\t\\treturn rgb;\\n\\n\\tvec3 lab = linear_srgb_to_oklab(rgb);\\n\\n\\tfloat L = lab.x;\\n\\tfloat eps = 0.00001f;\\n\\tfloat C = max(eps, sqrt(lab.y * lab.y + lab.z * lab.z));\\n\\tfloat a_ = lab.y / C;\\n\\tfloat b_ = lab.z / C;\\n\\n\\tfloat Ld = L - 0.5f;\\n\\tfloat e1 = 0.5f + abs(Ld) + alpha * C;\\n\\tfloat L0 = 0.5f * (1.f + sign(Ld) * (e1 - sqrt(e1 * e1 - 2.f * abs(Ld))));\\n\\n\\tfloat t = find_gamut_intersection(a_, b_, L, C, L0);\\n\\tfloat L_clipped = L0 * (1.f - t) + t * L;\\n\\tfloat C_clipped = t * C;\\n\\n\\treturn oklab_to_linear_srgb(vec3( L_clipped, C_clipped * a_, C_clipped * b_ ));\\n}\\n\\nvec3 gamut_clip_adaptive_L0_L_cusp(vec3 rgb, float alpha)\\n{\\n\\tif (rgb.r < 1.f && rgb.g < 1.f && rgb.b < 1.f && rgb.r > 0.f && rgb.g > 0.f && rgb.b > 0.f)\\n\\t\\treturn rgb;\\n\\n\\tvec3 lab = linear_srgb_to_oklab(rgb);\\n\\n\\tfloat L = lab.x;\\n\\tfloat eps = 0.00001f;\\n\\tfloat C = max(eps, sqrt(lab.y * lab.y + lab.z * lab.z));\\n\\tfloat a_ = lab.y / C;\\n\\tfloat b_ = lab.z / C;\\n\\n\\t// The cusp is computed here and in find_gamut_intersection, an optimized solution would only compute it once.\\n\\tvec2 cusp = find_cusp(a_, b_);\\n\\n\\tfloat Ld = L - cusp.x;\\n\\tfloat k = 2.f * (Ld > 0.f ? 1.f - cusp.x : cusp.x);\\n\\n\\tfloat e1 = 0.5f * k + abs(Ld) + alpha * C / k;\\n\\tfloat L0 = cusp.x + 0.5f * (sign(Ld) * (e1 - sqrt(e1 * e1 - 2.f * k * abs(Ld))));\\n\\n\\tfloat t = find_gamut_intersection(a_, b_, L, C, L0);\\n\\tfloat L_clipped = L0 * (1.f - t) + t * L;\\n\\tfloat C_clipped = t * C;\\n\\n\\treturn oklab_to_linear_srgb(vec3( L_clipped, C_clipped * a_, C_clipped * b_ ));\\n}\\n\\nfloat toe(float x)\\n{\\n\\tfloat k_1 = 0.206f;\\n\\tfloat k_2 = 0.03f;\\n\\tfloat k_3 = (1.f + k_1) / (1.f + k_2);\\n\\treturn 0.5f * (k_3 * x - k_1 + sqrt((k_3 * x - k_1) * (k_3 * x - k_1) + 4.f * k_2 * k_3 * x));\\n}\\n\\nfloat toe_inv(float x)\\n{\\n\\tfloat k_1 = 0.206f;\\n\\tfloat k_2 = 0.03f;\\n\\tfloat k_3 = (1.f + k_1) / (1.f + k_2);\\n\\treturn (x * x + k_1 * x) / (k_3 * (x + k_2));\\n}\\n\\nvec2 to_ST(vec2 cusp)\\n{\\n\\tfloat L = cusp.x;\\n\\tfloat C = cusp.y;\\n\\treturn vec2( C / L, C / (1.f - L) );\\n}\\n\\n// Returns a smooth approximation of the location of the cusp\\n// This polynomial was created by an optimization process\\n// It has been designed so that S_mid < S_max and T_mid < T_max\\nvec2 get_ST_mid(float a_, float b_)\\n{\\n\\tfloat S = 0.11516993f + 1.f / (\\n\\t\\t+7.44778970f + 4.15901240f * b_\\n\\t\\t+ a_ * (-2.19557347f + 1.75198401f * b_\\n\\t\\t\\t+ a_ * (-2.13704948f - 10.02301043f * b_\\n\\t\\t\\t\\t+ a_ * (-4.24894561f + 5.38770819f * b_ + 4.69891013f * a_\\n\\t\\t\\t\\t\\t)))\\n\\t\\t);\\n\\n\\tfloat T = 0.11239642f + 1.f / (\\n\\t\\t+1.61320320f - 0.68124379f * b_\\n\\t\\t+ a_ * (+0.40370612f + 0.90148123f * b_\\n\\t\\t\\t+ a_ * (-0.27087943f + 0.61223990f * b_\\n\\t\\t\\t\\t+ a_ * (+0.00299215f - 0.45399568f * b_ - 0.14661872f * a_\\n\\t\\t\\t\\t\\t)))\\n\\t\\t);\\n\\n\\treturn vec2( S, T );\\n}\\n\\nvec3 get_Cs(float L, float a_, float b_)\\n{\\n\\tvec2 cusp = find_cusp(a_, b_);\\n\\n\\tfloat C_max = find_gamut_intersection(a_, b_, L, 1.f, L, cusp);\\n\\tvec2 ST_max = to_ST(cusp);\\n\\t\\n\\t// Scale factor to compensate for the curved part of gamut shape:\\n\\tfloat k = C_max / min((L * ST_max.x), (1.f - L) * ST_max.y);\\n\\n\\tfloat C_mid;\\n\\t{\\n\\t\\tvec2 ST_mid = get_ST_mid(a_, b_);\\n\\n\\t\\t// Use a soft minimum function, instead of a sharp triangle shape to get a smooth value for chroma.\\n\\t\\tfloat C_a = L * ST_mid.x;\\n\\t\\tfloat C_b = (1.f - L) * ST_mid.y;\\n\\t\\tC_mid = 0.9f * k * sqrt(sqrt(1.f / (1.f / (C_a * C_a * C_a * C_a) + 1.f / (C_b * C_b * C_b * C_b))));\\n\\t}\\n\\n\\tfloat C_0;\\n\\t{\\n\\t\\t// for C_0, the shape is independent of hue, so vec2 are constant. Values picked to roughly be the average values of vec2.\\n\\t\\tfloat C_a = L * 0.4f;\\n\\t\\tfloat C_b = (1.f - L) * 0.8f;\\n\\n\\t\\t// Use a soft minimum function, instead of a sharp triangle shape to get a smooth value for chroma.\\n\\t\\tC_0 = sqrt(1.f / (1.f / (C_a * C_a) + 1.f / (C_b * C_b)));\\n\\t}\\n\\n\\treturn vec3( C_0, C_mid, C_max );\\n}\\n\\nvec3 okhsl_to_srgb(vec3 hsl)\\n{\\n\\tfloat h = hsl.x;\\n\\tfloat s = hsl.y;\\n\\tfloat l = hsl.z;\\n\\n\\tif (l == 1.0f)\\n\\t{\\n\\t\\treturn vec3( 1.f, 1.f, 1.f );\\n\\t}\\n\\n\\telse if (l == 0.f)\\n\\t{\\n\\t\\treturn vec3( 0.f, 0.f, 0.f );\\n\\t}\\n\\n\\tfloat a_ = cos(2.f * M_PI * h);\\n\\tfloat b_ = sin(2.f * M_PI * h);\\n\\tfloat L = toe_inv(l);\\n\\n\\tvec3 cs = get_Cs(L, a_, b_);\\n\\tfloat C_0 = cs.x;\\n\\tfloat C_mid = cs.y;\\n\\tfloat C_max = cs.z;\\n\\n\\tfloat mid = 0.8f;\\n\\tfloat mid_inv = 1.25f;\\n\\n\\tfloat C, t, k_0, k_1, k_2;\\n\\n\\tif (s < mid)\\n\\t{\\n\\t\\tt = mid_inv * s;\\n\\n\\t\\tk_1 = mid * C_0;\\n\\t\\tk_2 = (1.f - k_1 / C_mid);\\n\\n\\t\\tC = t * k_1 / (1.f - k_2 * t);\\n\\t}\\n\\telse\\n\\t{\\n\\t\\tt = (s - mid)/ (1.f - mid);\\n\\n\\t\\tk_0 = C_mid;\\n\\t\\tk_1 = (1.f - mid) * C_mid * C_mid * mid_inv * mid_inv / C_0;\\n\\t\\tk_2 = (1.f - (k_1) / (C_max - C_mid));\\n\\n\\t\\tC = k_0 + t * k_1 / (1.f - k_2 * t);\\n\\t}\\n\\n\\tvec3 rgb = oklab_to_linear_srgb(vec3( L, C * a_, C * b_ ));\\n\\treturn vec3(\\n\\t\\tsrgb_transfer_function(rgb.r),\\n\\t\\tsrgb_transfer_function(rgb.g),\\n\\t\\tsrgb_transfer_function(rgb.b)\\n\\t);\\n}\\n\\nvec3 srgb_to_okhsl(vec3 rgb)\\n{\\n\\tvec3 lab = linear_srgb_to_oklab(vec3(\\n\\t\\tsrgb_transfer_function_inv(rgb.r),\\n\\t\\tsrgb_transfer_function_inv(rgb.g),\\n\\t\\tsrgb_transfer_function_inv(rgb.b)\\n\\t\\t));\\n\\n\\tfloat C = sqrt(lab.y * lab.y + lab.z * lab.z);\\n\\tfloat a_ = lab.y / C;\\n\\tfloat b_ = lab.z / C;\\n\\n\\tfloat L = lab.x;\\n\\tfloat h = 0.5f + 0.5f * atan(-lab.z, -lab.y) / M_PI;\\n\\n\\tvec3 cs = get_Cs(L, a_, b_);\\n\\tfloat C_0 = cs.x;\\n\\tfloat C_mid = cs.y;\\n\\tfloat C_max = cs.z;\\n\\n\\t// Inverse of the interpolation in okhsl_to_srgb:\\n\\n\\tfloat mid = 0.8f;\\n\\tfloat mid_inv = 1.25f;\\n\\n\\tfloat s;\\n\\tif (C < C_mid)\\n\\t{\\n\\t\\tfloat k_1 = mid * C_0;\\n\\t\\tfloat k_2 = (1.f - k_1 / C_mid);\\n\\n\\t\\tfloat t = C / (k_1 + k_2 * C);\\n\\t\\ts = t * mid;\\n\\t}\\n\\telse\\n\\t{\\n\\t\\tfloat k_0 = C_mid;\\n\\t\\tfloat k_1 = (1.f - mid) * C_mid * C_mid * mid_inv * mid_inv / C_0;\\n\\t\\tfloat k_2 = (1.f - (k_1) / (C_max - C_mid));\\n\\n\\t\\tfloat t = (C - k_0) / (k_1 + k_2 * (C - k_0));\\n\\t\\ts = mid + (1.f - mid) * t;\\n\\t}\\n\\n\\tfloat l = toe(L);\\n\\treturn vec3( h, s, l );\\n}\\n\\n\\nvec3 okhsv_to_srgb(vec3 hsv)\\n{\\n\\tfloat h = hsv.x;\\n\\tfloat s = hsv.y;\\n\\tfloat v = hsv.z;\\n\\n\\tfloat a_ = cos(2.f * M_PI * h);\\n\\tfloat b_ = sin(2.f * M_PI * h);\\n\\t\\n\\tvec2 cusp = find_cusp(a_, b_);\\n\\tvec2 ST_max = to_ST(cusp);\\n\\tfloat S_max = ST_max.x;\\n\\tfloat T_max = ST_max.y;\\n\\tfloat S_0 = 0.5f;\\n\\tfloat k = 1.f- S_0 / S_max;\\n\\n\\t// first we compute L and V as if the gamut is a perfect triangle:\\n\\n\\t// L, C when v==1:\\n\\tfloat L_v = 1.f - s * S_0 / (S_0 + T_max - T_max * k * s);\\n\\tfloat C_v = s * T_max * S_0 / (S_0 + T_max - T_max * k * s);\\n\\n\\tfloat L = v * L_v;\\n\\tfloat C = v * C_v;\\n\\n\\t// then we compensate for both toe and the curved top part of the triangle:\\n\\tfloat L_vt = toe_inv(L_v);\\n\\tfloat C_vt = C_v * L_vt / L_v;\\n\\n\\tfloat L_new = toe_inv(L);\\n\\tC = C * L_new / L;\\n\\tL = L_new;\\n\\n\\tvec3 rgb_scale = oklab_to_linear_srgb(vec3( L_vt, a_ * C_vt, b_ * C_vt ));\\n\\tfloat scale_L = cbrt(1.f / max(max(rgb_scale.r, rgb_scale.g), max(rgb_scale.b, 0.f)));\\n\\n\\tL = L * scale_L;\\n\\tC = C * scale_L;\\n\\n\\tvec3 rgb = oklab_to_linear_srgb(vec3( L, C * a_, C * b_ ));\\n\\treturn vec3(\\n\\t\\tsrgb_transfer_function(rgb.r),\\n\\t\\tsrgb_transfer_function(rgb.g),\\n\\t\\tsrgb_transfer_function(rgb.b)\\n\\t);\\n}\\n\\nvec3 srgb_to_okhsv(vec3 rgb)\\n{\\n\\tvec3 lab = linear_srgb_to_oklab(vec3(\\n\\t\\tsrgb_transfer_function_inv(rgb.r),\\n\\t\\tsrgb_transfer_function_inv(rgb.g),\\n\\t\\tsrgb_transfer_function_inv(rgb.b)\\n\\t\\t));\\n\\n\\tfloat C = sqrt(lab.y * lab.y + lab.z * lab.z);\\n\\tfloat a_ = lab.y / C;\\n\\tfloat b_ = lab.z / C;\\n\\n\\tfloat L = lab.x;\\n\\tfloat h = 0.5f + 0.5f * atan(-lab.z, -lab.y) / M_PI;\\n\\n\\tvec2 cusp = find_cusp(a_, b_);\\n\\tvec2 ST_max = to_ST(cusp);\\n\\tfloat S_max = ST_max.x;\\n\\tfloat T_max = ST_max.y;\\n\\tfloat S_0 = 0.5f;\\n\\tfloat k = 1.f - S_0 / S_max;\\n\\n\\t// first we find L_v, C_v, L_vt and C_vt\\n\\n\\tfloat t = T_max / (C + L * T_max);\\n\\tfloat L_v = t * L;\\n\\tfloat C_v = t * C;\\n\\n\\tfloat L_vt = toe_inv(L_v);\\n\\tfloat C_vt = C_v * L_vt / L_v;\\n\\n\\t// we can then use these to invert the step that compensates for the toe and the curved top part of the triangle:\\n\\tvec3 rgb_scale = oklab_to_linear_srgb(vec3( L_vt, a_ * C_vt, b_ * C_vt ));\\n\\tfloat scale_L = cbrt(1.f / max(max(rgb_scale.r, rgb_scale.g), max(rgb_scale.b, 0.f)));\\n\\n\\tL = L / scale_L;\\n\\tC = C / scale_L;\\n\\n\\tC = C * toe(L) / L;\\n\\tL = toe(L);\\n\\n\\t// we can now compute v and s:\\n\\n\\tfloat v = L / L_v;\\n\\tfloat s = (S_0 + T_max) * C_v / ((T_max * S_0) + T_max * k * C_v);\\n\\n\\treturn vec3 (h, s, v );\\n}\"","export default \"vec3 hsl2rgb( in vec3 c ) {\\n vec3 rgb = clamp( abs(mod(c.x*6.0+vec3(0.0,4.0,2.0),6.0)-3.0)-1.0, 0.0, 1.0 );\\n return c.z + c.y * (rgb-0.5)*(1.0-abs(2.0*c.z-1.0));\\n}\"","export default \"vec3 hsv2rgb(vec3 c) {\\n vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\\n vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\\n return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\\n}\"","export default \"// slightly rearranged vector components so it matches with LCH\\n// M_PI and srgb_transfer_function are provided by oklab.frag.glsl (included before this file)\\nvec3 lch2rgb(vec3 lch) {\\n lch.y *= 0.34;\\n\\n vec3 lab = vec3(\\n lch.x,\\n lch.y * cos(lch.z * M_PI*2.0),\\n lch.y * sin(lch.z * M_PI*2.0)\\n );\\n\\n vec3 lms = vec3(\\n lab.x + 0.3963377774f * lab.y + 0.2158037573f * lab.z,\\n lab.x - 0.1055613458f * lab.y - 0.0638541728f * lab.z,\\n lab.x - 0.0894841775f * lab.y - 1.2914855480f * lab.z\\n );\\n\\n lms = pow(max(lms, vec3(0.0)), vec3(3.0));\\n\\n vec3 rgb = vec3(\\n +4.0767416621f * lms.x - 3.3077115913f * lms.y + 0.2309699292f * lms.z,\\n -1.2684380046f * lms.x + 2.6097574011f * lms.y - 0.3413193965f * lms.z,\\n -0.0041960863f * lms.x - 0.7034186147f * lms.y + 1.7076147010f * lms.z\\n );\\n\\n return vec3(\\n srgb_transfer_function(rgb.r),\\n srgb_transfer_function(rgb.g),\\n srgb_transfer_function(rgb.b)\\n );\\n}\\n\"","export default \"// Kotsarenko/Ramos weighted RGB distance.\\n// Operates on sRGB values directly (no linearisation needed).\\n// Weights red and blue channels by the mean red value, which improves\\n// perceptual uniformity compared to plain Euclidean RGB at minimal cost.\\nfloat kotsarenkoRamos(vec3 c1, vec3 c2) {\\n float rMean = (c1.r + c2.r) * 0.5;\\n vec3 d = c1 - c2;\\n return sqrt((2.0 + rMean) * d.r*d.r + 4.0 * d.g*d.g + (3.0 - rMean) * d.b*d.b);\\n}\\n\\n// ── CIELab ────────────────────────────────────────────────────────────────────\\n// sRGB -> XYZ (D65) -> CIELab\\n// Depends on: srgb2rgb() from srgb2rgb.frag.glsl, cbrt() from oklab.frag.glsl\\n\\nfloat _lab_f(float t) {\\n float delta = 6.0 / 29.0;\\n return t > delta * delta * delta\\n ? cbrt(t)\\n : t / (3.0 * delta * delta) + 4.0 / 29.0;\\n}\\n\\nvec3 srgb_to_cielab(vec3 srgb) {\\n vec3 lin = srgb2rgb(srgb);\\n\\n // Linear sRGB -> XYZ (D65 illuminant)\\n vec3 xyz = vec3(\\n 0.4124564 * lin.r + 0.3575761 * lin.g + 0.1804375 * lin.b,\\n 0.2126729 * lin.r + 0.7151522 * lin.g + 0.0721750 * lin.b,\\n 0.0193339 * lin.r + 0.1191920 * lin.g + 0.9503041 * lin.b\\n );\\n\\n // XYZ -> Lab (D65 white point: 0.95047, 1.00000, 1.08883)\\n float fx = _lab_f(xyz.x / 0.95047);\\n float fy = _lab_f(xyz.y);\\n float fz = _lab_f(xyz.z / 1.08883);\\n\\n return vec3(\\n 116.0 * fy - 16.0, // L*\\n 500.0 * (fx - fy), // a*\\n 200.0 * (fy - fz) // b*\\n );\\n}\\n\\n// CIE76: plain Euclidean distance in CIELab\\nfloat deltaE76(vec3 lab1, vec3 lab2) {\\n vec3 d = lab1 - lab2;\\n return sqrt(d.x*d.x + d.y*d.y + d.z*d.z);\\n}\\n\\n// CIEDE2000\\nfloat deltaE2000(vec3 lab1, vec3 lab2) {\\n float L1 = lab1.x, a1 = lab1.y, b1 = lab1.z;\\n float L2 = lab2.x, a2 = lab2.y, b2 = lab2.z;\\n\\n // Chroma\\n float C1 = sqrt(a1*a1 + b1*b1);\\n float C2 = sqrt(a2*a2 + b2*b2);\\n float Cavg = (C1 + C2) * 0.5;\\n float Cavg7 = pow(Cavg, 7.0);\\n\\n // G factor: adjustment to a* axis\\n float G = 0.5 * (1.0 - sqrt(Cavg7 / (Cavg7 + 6103515625.0))); // 25^7\\n\\n float a1p = a1 * (1.0 + G);\\n float a2p = a2 * (1.0 + G);\\n float C1p = sqrt(a1p*a1p + b1*b1);\\n float C2p = sqrt(a2p*a2p + b2*b2);\\n\\n // Guard atan(0,0): GLSL ES leaves that undefined, so skip it for achromatic colors.\\n // When a color has no chroma its hue angle is meaningless — we just need it to\\n // be a well-defined number so it doesn't corrupt the rest of the formula.\\n bool c1Achromatic = C1p < 1e-6;\\n bool c2Achromatic = C2p < 1e-6;\\n\\n float h1p = c1Achromatic ? 0.0 : atan(b1, a1p);\\n if (h1p < 0.0) h1p += TWO_PI;\\n float h2p = c2Achromatic ? 0.0 : atan(b2, a2p);\\n if (h2p < 0.0) h2p += TWO_PI;\\n\\n // Deltas\\n float dLp = L2 - L1;\\n float dCp = C2p - C1p;\\n\\n float dhp = 0.0;\\n if (!c1Achromatic && !c2Achromatic) {\\n dhp = h2p - h1p;\\n if (dhp > M_PI) dhp -= TWO_PI;\\n else if (dhp < -M_PI) dhp += TWO_PI;\\n }\\n float dHp = 2.0 * sqrt(C1p * C2p) * sin(dhp * 0.5);\\n\\n // Averages\\n float Lp = (L1 + L2) * 0.5;\\n float Cp = (C1p + C2p) * 0.5;\\n\\n // When one color is achromatic, its hue is 0 and the average is simply the other's hue\\n float hp;\\n if (c1Achromatic || c2Achromatic) {\\n hp = h1p + h2p;\\n } else if (abs(h1p - h2p) <= M_PI) {\\n hp = (h1p + h2p) * 0.5;\\n } else if (h1p + h2p < TWO_PI) {\\n hp = (h1p + h2p + TWO_PI) * 0.5;\\n } else {\\n hp = (h1p + h2p - TWO_PI) * 0.5;\\n }\\n\\n float T = 1.0\\n - 0.17 * cos(hp - radians(30.0))\\n + 0.24 * cos(2.0 * hp)\\n + 0.32 * cos(3.0 * hp + radians(6.0))\\n - 0.20 * cos(4.0 * hp - radians(63.0));\\n\\n // Weighting functions\\n float Lpm50sq = (Lp - 50.0) * (Lp - 50.0);\\n float SL = 1.0 + 0.015 * Lpm50sq / sqrt(20.0 + Lpm50sq);\\n float SC = 1.0 + 0.045 * Cp;\\n float SH = 1.0 + 0.015 * Cp * T;\\n\\n // Rotation term\\n float Cp7 = pow(Cp, 7.0);\\n float RC = 2.0 * sqrt(Cp7 / (Cp7 + 6103515625.0));\\n float hpDeg = degrees(hp);\\n float dTheta = radians(30.0) * exp(-((hpDeg - 275.0) / 25.0) * ((hpDeg - 275.0) / 25.0));\\n float RT = -sin(2.0 * dTheta) * RC;\\n\\n float dLn = dLp / SL;\\n float dCn = dCp / SC;\\n float dHn = dHp / SH;\\n\\n return sqrt(dLn*dLn + dCn*dCn + dHn*dHn + RT * dCn * dHn);\\n}\\n\"","export default \"// distanceMetric uniform: 0 = rgb, 1 = oklab, 2 = deltaE76, 3 = deltaE2000\\nvec3 closestColor(vec3 color, sampler2D paletteTexture, int paletteSize) {\\n float minDist = 1000000.0;\\n vec3 closest = vec3(0.0);\\n\\n for (int i = 0; i < paletteSize; i++) {\\n vec3 paletteColor = texture2D(paletteTexture, vec2(float(i) / float(paletteSize), 0.5)).rgb;\\n\\n float dist;\\n if (distanceMetric == 1) {\\n // OKLab: perceptually uniform Euclidean distance\\n dist = distance(linear_srgb_to_oklab(srgb2rgb(color)), linear_srgb_to_oklab(srgb2rgb(paletteColor)));\\n } else if (distanceMetric == 2) {\\n // CIE76: Euclidean distance in CIELab\\n dist = deltaE76(srgb_to_cielab(color), srgb_to_cielab(paletteColor));\\n } else if (distanceMetric == 3) {\\n // CIEDE2000: perceptually weighted color difference\\n dist = deltaE2000(srgb_to_cielab(color), srgb_to_cielab(paletteColor));\\n } else if (distanceMetric == 4) {\\n // Kotsarenko/Ramos: weighted RGB distance (fast, no conversion needed)\\n dist = kotsarenkoRamos(color, paletteColor);\\n } else {\\n // RGB: plain Euclidean distance in sRGB space\\n dist = distance(color, paletteColor);\\n }\\n\\n if (dist < minDist) {\\n minDist = dist;\\n closest = paletteColor;\\n }\\n }\\n\\n return closest;\\n}\\n\"","import {\n Color,\n DataTexture,\n Texture,\n RGBAFormat,\n FloatType,\n ClampToEdgeWrapping,\n NearestFilter,\n LinearFilter,\n ShaderMaterial,\n Scene,\n OrthographicCamera,\n PerspectiveCamera,\n WebGLRenderer,\n WebGLRenderTarget,\n PlaneGeometry,\n BoxGeometry,\n CylinderGeometry,\n SphereGeometry,\n InstancedMesh,\n MeshStandardMaterial,\n Mesh,\n Object3D,\n Vector3,\n AmbientLight,\n DirectionalLight,\n DoubleSide,\n} from \"three\";\n\nimport {\n ColorString,\n ColorList,\n PaletteVizOptions,\n PaletteViz3DOptions,\n PaletteViz3DVoronoiOptions,\n SupportedColorModels,\n Axis,\n DistanceMetric,\n} from \"./types.ts\";\n\n// @ts-ignore\nimport shaderSRGB2RGB from \"./shaders/srgb2rgb.frag.glsl?raw\" assert { type: \"raw\" };\n// @ts-ignore\nimport shaderOKLab from \"./shaders/oklab.frag.glsl?raw\" assert { type: \"raw\" };\n// @ts-ignore\nimport shaderHSL2RGB from \"./shaders/hsl2rgb.frag.glsl?raw\" assert { type: \"raw\" };\n// @ts-ignore\nimport shaderHSV2RGB from \"./shaders/hsv2rgb.frag.glsl?raw\" assert { type: \"raw\" };\n// @ts-ignore\nimport shaderLCH2RGB from \"./shaders/lch2rgb.frag.glsl?raw\" assert { type: \"raw\" };\n// @ts-ignore\nimport shaderDeltaE from \"./shaders/deltaE.frag.glsl?raw\" assert { type: \"raw\" };\n// @ts-ignore\nimport shaderClosestColor from \"./shaders/closestColor.frag.glsl?raw\" assert { type: \"raw\" };\n\n// Include order matters:\n// srgb2rgb – srgb2rgb()\n// oklab – M_PI, cbrt(), srgb_transfer_function(), okhsv/okhsl_to_srgb(), …\n// hsl2rgb, hsv2rgb, lch2rgb – color model conversions (lch2rgb uses M_PI + srgb_transfer_function)\n// deltaE – srgb_to_cielab(), deltaE76(), deltaE2000() (uses srgb2rgb, cbrt, M_PI, TWO_PI)\n// closestColor – branches on distanceMetric uniform; uses everything above\nexport const fragmentShader = `\n#define TWO_PI 6.28318530718\nvarying vec2 vUv;\nuniform float progress;\nuniform bool isPolar;\nuniform int distanceMetric;\nuniform int progress_axis;\nuniform sampler2D paletteTexture;\nuniform int paletteLength;\nuniform bool debug;\nuniform int polarColorModel;\nuniform bool invertZ;\n\n${shaderSRGB2RGB}\n${shaderOKLab}\n${shaderHSL2RGB}\n${shaderHSV2RGB}\n${shaderLCH2RGB}\n${shaderDeltaE}\n${shaderClosestColor}\n\n// polarColorModel: 0=hsv, 1=okhsv, 2=hsl, 3=okhsl, 4=oklch\nvec3 polarToRGB(vec3 colorCoords) {\n if (polarColorModel == 0) {\n return hsv2rgb(colorCoords);\n } else if (polarColorModel == 1) {\n return okhsv_to_srgb(colorCoords);\n } else if (polarColorModel == 2) {\n return hsl2rgb(colorCoords);\n } else if (polarColorModel == 3) {\n return okhsl_to_srgb(colorCoords);\n } else {\n // oklch — lch2rgb uses the OKLab matrix so this is OKLCH\n return lch2rgb(vec3(colorCoords.z, colorCoords.y, colorCoords.x));\n }\n}\n\nvoid main(){\n vec3 colorCoords = vec3(progress, vUv.x, vUv.y);\n if(progress_axis == 1){\n colorCoords = vec3(vUv.x, progress, vUv.y);\n } else if(progress_axis == 2){\n colorCoords = vec3(vUv.x, vUv.y, 1. - progress);\n }\n\n if(isPolar) {\n vec2 toCenter = vUv - 0.5;\n float angle = atan(toCenter.y, toCenter.x);\n float radius = length(toCenter) * 2.0;\n\n if(progress_axis == 2){\n colorCoords = vec3((angle / TWO_PI), radius, 1. - progress);\n } else if(progress_axis == 1){\n colorCoords = vec3((angle / TWO_PI), 1. - progress, radius);\n if (radius > 1.0) {\n discard;\n }\n } else {\n float hue = 1.0 - abs(0.5 - progress * .5) * 2.0;\n if (vUv.x > 0.5) {\n hue += 0.5;\n }\n colorCoords = vec3(hue, abs(0.5 - vUv.x) * 2.0, vUv.y);\n }\n }\n\n if(invertZ){\n colorCoords.z = 1. - colorCoords.z;\n }\n\n vec3 rgb = polarToRGB(colorCoords);\n vec3 closest = closestColor(rgb, paletteTexture, paletteLength);\n\n if (debug) {\n closest = rgb;\n }\n\n gl_FragColor = vec4(closest, 1.);\n}`;\n\n// Internal uniform shape — not part of the public API\ntype ShaderUniforms = {\n progress: { value: number };\n progress_axis: { value: number };\n polarColorModel: { value: number };\n isPolar: { value: boolean };\n distanceMetric: { value: number };\n paletteTexture: { value: DataTexture | null };\n paletteLength: { value: number };\n debug: { value: boolean };\n invertZ: { value: boolean };\n};\n\nconst vertexShader = `varying vec2 vUv;\n void main(){\n vUv = uv;\n gl_Position = vec4(position, 1.);\n }`;\n\n// Stores colors as sRGB so the shader's srgb2rgb() in closestColor correctly\n// converts them to linear before OKLab / CIELab distance calculations.\nexport const paletteToTexture = (palette: ColorList): DataTexture => {\n const data = new Float32Array(\n palette.flatMap((color) => {\n try {\n const c = new Color(color).convertLinearToSRGB();\n return [c.r, c.g, c.b, 1];\n } catch {\n console.error(`Invalid color: ${color}`);\n return [0, 0, 0, 1];\n }\n })\n );\n\n const texture = new DataTexture(data, palette.length, 1, RGBAFormat, FloatType);\n texture.needsUpdate = true;\n texture.wrapS = ClampToEdgeWrapping;\n texture.wrapT = ClampToEdgeWrapping;\n texture.minFilter = NearestFilter;\n texture.magFilter = NearestFilter;\n\n return texture;\n};\n\nexport const randomPalette = (size = 20): ColorList =>\n Array.from({ length: size }, () =>\n `rgb(${Math.floor(Math.random() * 256)}, ${Math.floor(Math.random() * 256)}, ${Math.floor(Math.random() * 256)})`\n );\n\nexport class PaletteViz {\n #palette: ColorList = [];\n #width = 512;\n #height = 512;\n #pixelRatio = 1;\n\n // shader state\n #position = 0.0;\n #axis: Axis = \"y\";\n #colorModel: SupportedColorModels = \"okhsv\";\n #distanceMetric: DistanceMetric = \"oklab\";\n #isPolar = true;\n #invertLightness = false;\n #showRaw = false;\n\n // uniform value maps\n readonly #axisMap = { x: 0, y: 1, z: 2 } as const;\n readonly #colorModelMap = { hsv: 0, okhsv: 1, hsl: 2, okhsl: 3, oklch: 4 } as const;\n readonly #distanceMetricMap = { rgb: 0, oklab: 1, deltaE76: 2, deltaE2000: 3, kotsarenkoRamos: 4 } as const;\n\n // three.js\n #texture!: DataTexture;\n #uniforms!: ShaderUniforms;\n #material!: ShaderMaterial;\n #geometry!: PlaneGeometry;\n #mesh!: Mesh;\n #renderer!: WebGLRenderer;\n #camera!: OrthographicCamera;\n #scene!: Scene;\n #animationFrame: number | null = null;\n\n // dom\n #container!: HTMLElement;\n\n constructor({\n palette = randomPalette(),\n width = 512,\n height = 512,\n pixelRatio = window.devicePixelRatio,\n container = document.body,\n colorModel = \"okhsv\",\n distanceMetric = \"oklab\",\n isPolar = true,\n axis = \"y\",\n position = 0.0,\n invertLightness = false,\n showRaw = false,\n }: PaletteVizOptions = {}) {\n this.#palette = palette;\n this.#width = width;\n this.#height = height;\n this.#pixelRatio = pixelRatio;\n this.#colorModel = colorModel;\n this.#distanceMetric = distanceMetric;\n this.#isPolar = isPolar;\n this.#axis = axis;\n this.#position = position;\n this.#invertLightness = invertLightness;\n this.#showRaw = showRaw;\n this.#container = container;\n\n this.#texture = paletteToTexture(this.#palette);\n this.#uniforms = {\n progress: { value: this.#position },\n progress_axis: { value: this.#axisMap[this.#axis] },\n polarColorModel:{ value: this.#colorModelMap[this.#colorModel] },\n isPolar: { value: this.#isPolar },\n distanceMetric: { value: this.#distanceMetricMap[this.#distanceMetric] },\n paletteTexture: { value: this.#texture },\n paletteLength: { value: this.#palette.length },\n debug: { value: this.#showRaw },\n invertZ: { value: this.#invertLightness },\n };\n\n this.#material = new ShaderMaterial({ uniforms: this.#uniforms, vertexShader, fragmentShader });\n this.#initThree();\n }\n\n #initThree() {\n this.#scene = new Scene();\n this.#camera = new OrthographicCamera(-1, 1, 1, -1, 0.1, 1);\n this.#renderer = new WebGLRenderer();\n this.#renderer.setPixelRatio(this.#pixelRatio);\n this.#renderer.setSize(this.#width, this.#height);\n this.#renderer.domElement.classList.add(\"palette-viz\");\n\n this.#geometry = new PlaneGeometry(2, 2);\n this.#mesh = new Mesh(this.#geometry, this.#material);\n this.#scene.add(this.#mesh);\n this.#container.appendChild(this.#renderer.domElement);\n\n this.#paint();\n }\n\n #paint() {\n if (this.#animationFrame !== null) {\n cancelAnimationFrame(this.#animationFrame);\n }\n this.#animationFrame = requestAnimationFrame(() => {\n this.#renderer.render(this.#scene, this.#camera);\n });\n }\n\n // ── Public API ────────────────────────────────────────────────────────────\n\n get canvas(): HTMLCanvasElement {\n return this.#renderer.domElement;\n }\n\n get width() { return this.#width; }\n get height() { return this.#height; }\n\n resize(width: number, height: number | null = null): void {\n this.#width = width;\n this.#height = height === null ? width : height;\n this.#renderer.setSize(this.#width, this.#height);\n this.#camera.updateProjectionMatrix();\n this.#paint();\n }\n\n destroy(): void {\n if (this.#animationFrame !== null) {\n cancelAnimationFrame(this.#animationFrame);\n this.#animationFrame = null;\n }\n this.#texture.dispose();\n this.#material.dispose();\n this.#geometry.dispose();\n this.#renderer.dispose();\n this.#renderer.domElement.remove();\n }\n\n // ── Palette ───────────────────────────────────────────────────────────────\n\n set palette(palette: ColorList) {\n this.#palette = palette;\n this.#texture = paletteToTexture(palette);\n this.#uniforms.paletteTexture.value = this.#texture;\n this.#uniforms.paletteLength.value = palette.length;\n this.#paint();\n }\n\n get palette() {\n return this.#palette;\n }\n\n setColor(color: ColorString, index: number): void {\n if (index < 0 || index >= this.#palette.length) {\n throw new Error(`Index ${index} out of range`);\n }\n this.#palette[index] = color;\n this.#texture = paletteToTexture(this.#palette);\n this.#uniforms.paletteTexture.value = this.#texture;\n this.#paint();\n }\n\n addColor(color: ColorString, index?: number): void {\n this.#palette.splice(index ?? this.#palette.length, 0, color);\n this.#texture = paletteToTexture(this.#palette);\n this.#uniforms.paletteTexture.value = this.#texture;\n this.#uniforms.paletteLength.value = this.#palette.length;\n this.#paint();\n }\n\n removeColor(index: number): void;\n removeColor(color: ColorString): void;\n removeColor(indexOrColor: number | ColorString): void {\n const index = typeof indexOrColor === \"number\"\n ? indexOrColor\n : this.#palette.indexOf(indexOrColor);\n if (index === -1) throw new Error(\"Color not found in palette\");\n if (index < 0 || index >= this.#palette.length) throw new Error(`Index ${index} out of range`);\n this.#palette.splice(index, 1);\n this.#texture = paletteToTexture(this.#palette);\n this.#uniforms.paletteTexture.value = this.#texture;\n this.#uniforms.paletteLength.value = this.#palette.length;\n this.#paint();\n }\n\n // ── Shader properties ─────────────────────────────────────────────────────\n\n set position(value: number) {\n this.#position = value;\n this.#uniforms.progress.value = value;\n this.#paint();\n }\n get position() { return this.#position; }\n\n set axis(axis: Axis) {\n if (!(axis in this.#axisMap)) throw new Error(\"axis must be 'x', 'y', or 'z'\");\n this.#axis = axis;\n this.#uniforms.progress_axis.value = this.#axisMap[axis];\n this.#paint();\n }\n get axis() { return this.#axis; }\n\n set colorModel(model: SupportedColorModels) {\n if (!(model in this.#colorModelMap)) throw new Error(\"colorModel must be 'hsv', 'okhsv', 'hsl', 'okhsl', or 'oklch'\");\n this.#colorModel = model;\n this.#uniforms.polarColorModel.value = this.#colorModelMap[model];\n this.#paint();\n }\n get colorModel() { return this.#colorModel; }\n\n set distanceMetric(metric: DistanceMetric) {\n if (!(metric in this.#distanceMetricMap)) throw new Error(\"distanceMetric must be 'rgb', 'oklab', 'deltaE76', 'deltaE2000', or 'kotsarenkoRamos'\");\n this.#distanceMetric = metric;\n this.#uniforms.distanceMetric.value = this.#distanceMetricMap[metric];\n this.#paint();\n }\n get distanceMetric() { return this.#distanceMetric; }\n\n set isPolar(value: boolean) {\n this.#isPolar = value;\n this.#uniforms.isPolar.value = value;\n this.#paint();\n }\n get isPolar() { return this.#isPolar; }\n\n set invertLightness(value: boolean) {\n this.#invertLightness = value;\n this.#uniforms.invertZ.value = value;\n this.#paint();\n }\n get invertLightness() { return this.#invertLightness; }\n\n set showRaw(value: boolean) {\n this.#showRaw = value;\n this.#uniforms.debug.value = value;\n this.#paint();\n }\n get showRaw() { return this.#showRaw; }\n\n static paletteToTexture = (palette: ColorList) => paletteToTexture(palette);\n}\n\n// ── PaletteViz3D ──────────────────────────────────────────────────────────────\n// N semi-transparent horizontal slices of the colour space stacked along the\n// value/lightness axis. The expensive Voronoi computation (closestColor) is\n// baked into a 2-D atlas texture ONCE per settings change; orbit is then a\n// free texture lookup with no per-frame distance math.\n\n// ── Compute pass ──────────────────────────────────────────────────────────────\n// A single full-screen quad bakes ALL slices into a tall atlas texture.\n// Each horizontal band in the atlas is one Z-slice of the colour space.\n// This runs once per palette/settings change — orbit never triggers it.\n\nconst computeVertShader3D = `\nvarying vec2 vUv;\nvoid main() {\n vUv = uv;\n gl_Position = vec4(position, 1.0);\n}`;\n\nconst computeFragShader3D = `\n#define TWO_PI 6.28318530718\nvarying vec2 vUv;\n\nuniform float slices;\nuniform bool isPolar;\nuniform int distanceMetric;\nuniform sampler2D paletteTexture;\nuniform int paletteLength;\nuniform bool debug;\nuniform int polarColorModel;\nuniform bool invertZ;\n\n${shaderSRGB2RGB}\n${shaderOKLab}\n${shaderHSL2RGB}\n${shaderHSV2RGB}\n${shaderLCH2RGB}\n${shaderDeltaE}\n${shaderClosestColor}\n\nvec3 polarToRGB(vec3 cc) {\n if (polarColorModel == 0) return hsv2rgb(cc);\n if (polarColorModel == 1) return okhsv_to_srgb(cc);\n if (polarColorModel == 2) return hsl2rgb(cc);\n if (polarColorModel == 3) return okhsl_to_srgb(cc);\n return lch2rgb(vec3(cc.z, cc.y, cc.x));\n}\n\nvoid main() {\n // Decode which slice and the UV within that slice from the atlas Y coordinate.\n float sliceF = vUv.y * slices;\n float progress = floor(sliceF) / (slices - 1.0); // 0…1 along value axis\n vec2 sliceUV = vec2(vUv.x, fract(sliceF));\n\n vec3 colorCoords;\n if (isPolar) {\n vec2 toCenter = sliceUV - 0.5;\n float angle = atan(toCenter.y, toCenter.x);\n float radius = length(toCenter) * 2.0;\n // Outside the unit circle: store black; display shader discards it.\n if (radius > 1.0) { gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); return; }\n colorCoords = vec3(angle / TWO_PI, radius, progress);\n } else {\n colorCoords = vec3(sliceUV.x, sliceUV.y, progress);\n }\n\n if (invertZ) colorCoords.z = 1.0 - colorCoords.z;\n\n vec3 rgb = polarToRGB(colorCoords);\n vec3 col = debug ? rgb : closestColor(rgb, paletteTexture, paletteLength);\n gl_FragColor = vec4(col, 1.0);\n}`;\n\n// ── Display pass ──────────────────────────────────────────────────────────────\n// N horizontal planes stacked along Y. Each samples from the precomputed atlas —\n// no colour-space math here at all.\n\nconst displayVertShader3D = `\nvarying vec3 vWorldPos;\nvoid main() {\n vec4 wp = modelMatrix * vec4(position, 1.0);\n vWorldPos = wp.xyz;\n gl_Position = projectionMatrix * viewMatrix * wp;\n}`;\n\nconst displayFragShader3D = `\nvarying vec3 vWorldPos;\n\nuniform sampler2D atlas;\nuniform float slices;\nuniform float opacity;\nuniform bool isPolar;\n\nvoid main() {\n // World-space XZ → slice UV, Y → progress along value axis\n vec2 sliceUV = vWorldPos.xz + 0.5;\n float progress = vWorldPos.y + 0.5;\n\n if (isPolar && length(sliceUV - 0.5) * 2.0 > 1.0) discard;\n\n float si = floor(progress * (slices - 1.0) + 0.5);\n float atlasV = (si + sliceUV.y) / slices;\n vec3 col = texture2D(atlas, vec2(sliceUV.x, atlasV)).rgb;\n\n gl_FragColor = vec4(col, opacity);\n}`;\n\n// ── Internal uniform types ────────────────────────────────────────────────────\n\ntype ComputeUniforms3D = {\n slices: { value: number };\n isPolar: { value: boolean };\n distanceMetric: { value: number };\n paletteTexture: { value: DataTexture | null };\n paletteLength: { value: number };\n debug: { value: boolean };\n polarColorModel: { value: number };\n invertZ: { value: boolean };\n};\n\ntype DisplayUniforms3D = {\n atlas: { value: Texture | null };\n slices: { value: number };\n opacity: { value: number };\n isPolar: { value: boolean };\n};\n\n// ── Class ─────────────────────────────────────────────────────────────────────\n\nexport class PaletteViz3D {\n #palette: ColorList = [];\n #width = 512;\n #height = 512;\n #pixelRatio = 1;\n #slices = 32;\n #sliceResolution = 64;\n\n #colorModel: SupportedColorModels = \"okhsv\";\n #distanceMetric: DistanceMetric = \"oklab\";\n #invertLightness = false;\n #showRaw = false;\n #isPolar = true;\n #sliceOpacity = 0.15;\n\n #yaw = 0.5;\n #pitch = 0.4;\n #zoom = 1.5;\n\n readonly #colorModelMap = { hsv: 0, okhsv: 1, hsl: 2, okhsl: 3, oklch: 4 } as const;\n readonly #distanceMetricMap = { rgb: 0, oklab: 1, deltaE76: 2, deltaE2000: 3, kotsarenkoRamos: 4 } as const;\n\n // compute pass\n #paletteTexture!: DataTexture;\n #computeUniforms!: ComputeUniforms3D;\n #computeMaterial!: ShaderMaterial;\n #computeScene!: Scene;\n #computeCamera!: OrthographicCamera;\n #atlasTarget!: WebGLRenderTarget;\n\n // display pass\n #displayUniforms!: DisplayUniforms3D;\n #displayMaterial!: ShaderMaterial;\n #slabMeshes: Mesh[] = [];\n #displayScene!: Scene;\n #displayCamera!: PerspectiveCamera;\n\n #renderer!: WebGLRenderer;\n #animationFrame: number | null = null;\n #container!: HTMLElement;\n #dragStart: { x: number; y: number; yaw: number; pitch: number } | null = null;\n\n constructor({\n palette = randomPalette(),\n width = 512,\n height = 512,\n pixelRatio = window.devicePixelRatio,\n container = document.body,\n colorModel = \"okhsv\",\n distanceMetric = \"oklab\",\n invertLightness = false,\n showRaw = false,\n isPolar = true,\n yaw = 0.5,\n pitch = 0.4,\n zoom = 1.5,\n slices = 32,\n sliceResolution = 64,\n sliceOpacity,\n }: PaletteViz3DOptions = {}) {\n this.#palette = palette;\n this.#width = width;\n this.#height = height;\n this.#pixelRatio = pixelRatio;\n this.#colorModel = colorModel;\n this.#distanceMetric = distanceMetric;\n this.#invertLightness = invertLightness;\n this.#showRaw = showRaw;\n this.#isPolar = isPolar;\n this.#yaw = yaw;\n this.#pitch = pitch;\n this.#zoom = zoom;\n this.#slices = Math.max(2, slices);\n this.#sliceResolution = sliceResolution;\n this.#sliceOpacity = sliceOpacity ?? Math.min(1, 5 / this.#slices);\n this.#container = container;\n\n this.#paletteTexture = paletteToTexture(this.#palette);\n this.#initThree();\n this.#initControls();\n this.#computeAtlas(); // bake once on startup\n this.#paint();\n }\n\n // ── Atlas precomputation ───────────────────────────────────────────────────\n\n #computeAtlas(): void {\n this.#computeUniforms.paletteTexture.value = this.#paletteTexture;\n this.#computeUniforms.paletteLength.value = this.#palette.length;\n this.#computeUniforms.polarColorModel.value = this.#colorModelMap[this.#colorModel];\n this.#computeUniforms.distanceMetric.value = this.#distanceMetricMap[this.#distanceMetric];\n this.#computeUniforms.debug.value = this.#showRaw;\n this.#computeUniforms.invertZ.value = this.#invertLightness;\n this.#computeUniforms.isPolar.value = this.#isPolar;\n\n this.#renderer.setRenderTarget(this.#atlasTarget);\n this.#renderer.render(this.#computeScene, this.#computeCamera);\n this.#renderer.setRenderTarget(null);\n }\n\n // Recompute atlas then repaint — called for any setting that changes the Voronoi.\n #invalidate(): void {\n this.#computeAtlas();\n this.#paint();\n }\n\n // ── Camera ────────────────────────────────────────────────────────────────\n\n #updateCamera(): void {\n const x = this.#zoom * Math.sin(this.#yaw) * Math.cos(this.#pitch);\n const y = this.#zoom * Math.sin(this.#pitch);\n const z = this.#zoom * Math.cos(this.#yaw) * Math.cos(this.#pitch);\n this.#displayCamera.position.set(x, y, z);\n this.#displayCamera.lookAt(0, 0, 0);\n }\n\n #paint(): void {\n if (this.#animationFrame !== null) cancelAnimationFrame(this.#animationFrame);\n this.#animationFrame = requestAnimationFrame(() => {\n // Sort slabs back-to-front: camera above → bottom first, camera below → top first\n const N = this.#slabMeshes.length;\n this.#slabMeshes.forEach((mesh, i) => {\n mesh.renderOrder = this.#pitch >= 0 ? i : N - 1 - i;\n });\n this.#renderer.render(this.#displayScene, this.#displayCamera);\n });\n }\n\n // ── Three.js setup ────────────────────────────────────────────────────────\n\n #initThree(): void {\n this.#renderer = new WebGLRenderer({ antialias: true });\n this.#renderer.setPixelRatio(this.#pixelRatio);\n this.#renderer.setSize(this.#width, this.#height);\n this.#renderer.domElement.classList.add(\"palette-viz-3d\");\n this.#container.appendChild(this.#renderer.domElement);\n\n // Atlas render target\n this.#atlasTarget = new WebGLRenderTarget(\n this.#sliceResolution,\n this.#sliceResolution * this.#slices,\n { minFilter: LinearFilter, magFilter: LinearFilter }\n );\n\n // Compute scene (full-screen quad, bakes the atlas)\n this.#computeUniforms = {\n slices: { value: this.#slices },\n isPolar: { value: this.#isPolar },\n distanceMetric: { value: this.#distanceMetricMap[this.#distanceMetric] },\n paletteTexture: { value: this.#paletteTexture },\n paletteLength: { value: this.#palette.length },\n debug: { value: this.#showRaw },\n polarColorModel: { value: this.#colorModelMap[this.#colorModel] },\n invertZ: { value: this.#invertLightness },\n };\n this.#computeMaterial = new ShaderMaterial({\n uniforms: this.#computeUniforms,\n vertexShader: computeVertShader3D,\n fragmentShader: computeFragShader3D,\n });\n this.#computeScene = new Scene();\n this.#computeCamera = new OrthographicCamera(-1, 1, 1, -1, 0.1, 1);\n this.#computeScene.add(new Mesh(new PlaneGeometry(2, 2), this.#computeMaterial));\n\n // Display scene (stacked slices, samples from atlas)\n this.#displayUniforms = {\n atlas: { value: this.#atlasTarget.texture },\n slices: { value: this.#slices },\n opacity: { value: this.#sliceOpacity },\n isPolar: { value: this.#isPolar },\n };\n this.#displayMaterial = new ShaderMaterial({\n uniforms: this.#displayUniforms,\n vertexShader: displayVertShader3D,\n fragmentShader: displayFragShader3D,\n transparent: true,\n depthWrite: false,\n side: DoubleSide,\n });\n const N = this.#slices;\n const slabH = N > 1 ? 1.001 / (N - 1) : 1; // slight overlap eliminates gaps\n\n this.#displayScene = new Scene();\n this.#displayCamera = new PerspectiveCamera(60, this.#width / this.#height, 0.01, 10);\n this.#slabMeshes = [];\n for (let i = 0; i < N; i++) {\n const mesh = new Mesh(new BoxGeometry(1, slabH, 1), this.#displayMaterial);\n mesh.position.y = N > 1 ? i / (N - 1) - 0.5 : 0;\n this.#displayScene.add(mesh);\n this.#slabMeshes.push(mesh);\n }\n this.#updateCamera();\n }\n\n #initControls(): void {\n const el = this.#renderer.domElement;\n\n el.addEventListener(\"pointerdown\", (e) => {\n this.#dragStart = { x: e.clientX, y: e.clientY, yaw: this.#yaw, pitch: this.#pitch };\n el.setPointerCapture(e.pointerId);\n });\n el.addEventListener(\"pointermove\", (e) => {\n if (!this.#dragStart) return;\n const dx = e.clientX - this.#dragStart.x;\n const dy = e.clientY - this.#dragStart.y;\n this.#yaw = this.#dragStart.yaw - dx * 0.005;\n this.#pitch = Math.max(-Math.PI / 2.1, Math.min(Math.PI / 2.1,\n this.#dragStart.pitch + dy * 0.005));\n this.#updateCamera();\n this.#paint();\n });\n el.addEventListener(\"pointerup\", () => { this.#dragStart = null; });\n el.addEventListener(\"pointercancel\", () => { this.#dragStart = null; });\n el.addEventListener(\"wheel\", (e) => {\n e.preventDefault();\n this.#zoom = Math.max(0.2, Math.min(5, this.#zoom + e.deltaY * 0.001));\n this.#updateCamera();\n this.#paint();\n }, { passive: false });\n }\n\n // ── Public API ─────────────────────────────────────────────────────────────\n\n get canvas(): HTMLCanvasElement { return this.#renderer.domElement; }\n get width() { return this.#width; }\n get height() { return this.#height; }\n\n resize(width: number, height: number | null = null): void {\n this.#width = width;\n this.#height = height ?? width;\n this.#renderer.setSize(this.#width, this.#height);\n this.#displayCamera.aspect = this.#width / this.#height;\n this.#displayCamera.updateProjectionMatrix();\n this.#paint();\n }\n\n destroy(): void {\n if (this.#animationFrame !== null) {\n cancelAnimationFrame(this.#animationFrame);\n this.#animationFrame = null;\n }\n this.#paletteTexture.dispose();\n this.#atlasTarget.dispose();\n this.#computeMaterial.dispose();\n this.#slabMeshes.forEach(m => m.geometry.dispose());\n this.#displayMaterial.dispose();\n this.#renderer.dispose();\n this.#renderer.domElement.remove();\n }\n\n // ── Palette ────────────────────────────────────────────────────────────────\n\n set palette(palette: ColorList) {\n this.#palette = palette;\n this.#paletteTexture = paletteToTexture(palette);\n this.#invalidate();\n }\n get palette() { return this.#palette; }\n\n setColor(color: ColorString, index: number): void {\n if (index < 0 || index >= this.#palette.length) throw new Error(`Index ${index} out of range`);\n this.#palette[index] = color;\n this.#paletteTexture = paletteToTexture(this.#palette);\n this.#invalidate();\n }\n\n // ── Shader properties — all trigger atlas recomputation ───────────────────\n\n set colorModel(model: SupportedColorModels) {\n this.#colorModel = model; this.#invalidate();\n }\n get colorModel() { return this.#colorModel; }\n\n set distanceMetric(metric: DistanceMetric) {\n this.#distanceMetric = metric; this.#invalidate();\n }\n get distanceMetric() { return this.#distanceMetric; }\n\n set isPolar(value: boolean) {\n this.#isPolar = value;\n this.#displayUniforms.isPolar.value = value;\n this.#invalidate();\n }\n get isPolar() { return this.#isPolar; }\n\n set invertLightness(value: boolean) {\n this.#invertLightness = value; this.#invalidate();\n }\n get invertLightness() { return this.#invertLightness; }\n\n set showRaw(value: boolean) {\n this.#showRaw = value; this.#invalidate();\n }\n get showRaw() { return this.#showRaw; }\n\n // ── Orbit — cheap repaint only, no recomputation ──────────────────────────\n\n set yaw(value: number) { this.#yaw = value; this.#updateCamera(); this.#paint(); }\n get yaw() { return this.#yaw; }\n\n set pitch(value: number) {\n this.#pitch = Math.max(-Math.PI / 2.1, Math.min(Math.PI / 2.1, value));\n this.#updateCamera(); this.#paint();\n }\n get pitch() { return this.#pitch; }\n\n set zoom(value: number) {\n this.#zoom = Math.max(0.2, Math.min(5, value));\n this.#updateCamera(); this.#paint();\n }\n get zoom() { return this.#zoom; }\n}\n\n// ── PaletteViz3DVoronoi ────────────────────────────────────────────────────────\n// Renders the Voronoi structure of a palette as a 3D tube wireframe.\n// Steps:\n// 1. GPU compute pass (same atlas shader as PaletteViz3D) labels each voxel\n// in an NxNxN grid with its nearest palette color.\n// 2. CPU readback: extract all grid edges where 3+ distinct Voronoi cells meet\n// — these are the 1D edges of the Voronoi polyhedra.\n// 3. Render those edges as instanced cylinders (tubes) + sphere joints.\n\nexport class PaletteViz3DVoronoi {\n #palette: ColorList = [];\n #width = 512;\n #height = 512;\n #pixelRatio = 1;\n #resolution = 32;\n #tubeRadius = 0.008;\n #tubeSegments = 8;\n\n #colorModel: SupportedColorModels = \"okhsv\";\n #distanceMetric: DistanceMetric = \"oklab\";\n #invertLightness = false;\n #showRaw = false;\n #isPolar = true;\n\n #yaw = 0.5;\n #pitch = 0.4;\n #zoom = 1.5;\n\n readonly #colorModelMap = { hsv: 0, okhsv: 1, hsl: 2, okhsl: 3, oklch: 4 } as const;\n readonly #distanceMetricMap = { rgb: 0, oklab: 1, deltaE76: 2, deltaE2000: 3, kotsarenkoRamos: 4 } as const;\n\n // compute pass — reuses module-level shader strings and ComputeUniforms3D type\n #paletteTexture!: DataTexture;\n #computeUniforms!: ComputeUniforms3D;\n #computeMaterial!: ShaderMaterial;\n #computeScene!: Scene;\n #computeCamera!: OrthographicCamera;\n #atlasTarget!: WebGLRenderTarget;\n\n // display\n #displayScene!: Scene;\n #displayCamera!: PerspectiveCamera;\n #tubeMesh: InstancedMesh | null = null;\n #nodeMesh: InstancedMesh | null = null;\n #tubeMaterial!: MeshStandardMaterial;\n\n #renderer!: WebGLRenderer;\n #animationFrame: number | null = null;\n #container!: HTMLElement;\n #dragStart: { x: number; y: number; yaw: number; pitch: number } | null = null;\n\n constructor({\n palette = randomPalette(),\n width = 512,\n height = 512,\n pixelRatio = window.devicePixelRatio,\n container = document.body,\n colorModel = \"okhsv\",\n distanceMetric = \"oklab\",\n invertLightness = false,\n showRaw = false,\n isPolar = true,\n yaw = 0.5,\n pitch = 0.4,\n zoom = 1.5,\n resolution = 32,\n tubeRadius = 0.008,\n tubeSegments = 8,\n }: PaletteViz3DVoronoiOptions = {}) {\n this.#palette = palette;\n this.#width = width;\n this.#height = height;\n this.#pixelRatio = pixelRatio;\n this.#colorModel = colorModel;\n this.#distanceMetric = distanceMetric;\n this.#invertLightness = invertLightness;\n this.#showRaw = showRaw;\n this.#isPolar = isPolar;\n this.#yaw = yaw;\n this.#pitch = pitch;\n this.#zoom = zoom;\n this.#resolution = Math.max(4, resolution);\n this.#tubeRadius = tubeRadius;\n this.#tubeSegments = tubeSegments;\n this.#container = container;\n\n this.#paletteTexture = paletteToTexture(this.#palette);\n this.#initThree();\n this.#initControls();\n this.#rebuild();\n }\n\n #initThree(): void {\n this.#renderer = new WebGLRenderer({ antialias: true });\n this.#renderer.setPixelRatio(this.#pixelRatio);\n this.#renderer.setSize(this.#width, this.#height);\n this.#renderer.setClearColor(0x111111);\n this.#renderer.domElement.classList.add(\"palette-viz-voronoi\");\n this.#container.appendChild(this.#renderer.domElement);\n\n const res = this.#resolution;\n\n // NearestFilter atlas — crisp voxel labels, no interpolation blurring edges\n this.#atlasTarget = new WebGLRenderTarget(res, res * res, {\n minFilter: NearestFilter,\n magFilter: NearestFilter,\n });\n\n this.#computeUniforms = {\n slices: { value: res },\n isPolar: { value: this.#isPolar },\n distanceMetric: { value: this.#distanceMetricMap[this.#distanceMetric] },\n paletteTexture: { value: this.#paletteTexture },\n paletteLength: { value: this.#palette.length },\n debug: { value: this.#showRaw },\n polarColorModel: { value: this.#colorModelMap[this.#colorModel] },\n invertZ: { value: this.#invertLightness },\n };\n this.#computeMaterial = new ShaderMaterial({\n uniforms: this.#computeUniforms,\n vertexShader: computeVertShader3D,\n fragmentShader: computeFragShader3D,\n });\n this.#computeScene = new Scene();\n this.#computeCamera = new OrthographicCamera(-1, 1, 1, -1, 0.1, 1);\n this.#computeScene.add(new Mesh(new PlaneGeometry(2, 2), this.#computeMaterial));\n\n this.#displayScene = new Scene();\n this.#displayCamera = new PerspectiveCamera(60, this.#width / this.#height, 0.01, 10);\n this.#displayScene.add(new AmbientLight(0xffffff, 0.5));\n const dirLight = new DirectionalLight(0xffffff, 1.5);\n dirLight.position.set(2, 3, 2);\n this.#displayScene.add(dirLight);\n this.#tubeMaterial = new MeshStandardMaterial({ roughness: 0.35, metalness: 0.1, vertexColors: true });\n\n this.#updateCamera();\n }\n\n #computeAtlas(): void {\n this.#computeUniforms.paletteTexture.value = this.#paletteTexture;\n this.#computeUniforms.paletteLength.value = this.#palette.length;\n this.#computeUniforms.polarColorModel.value = this.#colorModelMap[this.#colorModel];\n this.#computeUniforms.distanceMetric.value = this.#distanceMetricMap[this.#distanceMetric];\n this.#computeUniforms.debug.value = this.#showRaw;\n this.#computeUniforms.invertZ.value = this.#invertLightness;\n this.#computeUniforms.isPolar.value = this.#isPolar;\n\n this.#renderer.setRenderTarget(this.#atlasTarget);\n this.#renderer.render(this.#computeScene, this.#computeCamera);\n this.#renderer.setRenderTarget(null);\n }\n\n // Returns an encoded color label (R<<16|G<<8|B) for a voxel, or null if\n // the voxel is out of bounds or (in polar mode) outside the unit disc.\n #getLabel(pixels: Uint8Array, ix: number, iy: number, iz: number): number | null {\n const N = this.#resolution;\n if (ix < 0 || ix >= N || iy < 0 || iy >= N || iz < 0 || iz >= N) return null;\n if (this.#isPolar) {\n const sx = (ix + 0.5) / N - 0.5;\n const sy = (iy + 0.5) / N - 0.5;\n if (Math.sqrt(sx * sx + sy * sy) * 2.0 > 1.0) return null;\n }\n const offset = ((iz * N + iy) * N + ix) * 4;\n return (pixels[offset] << 16) | (pixels[offset + 1] << 8) | pixels[offset + 2];\n }\n\n // Atlas corner (cx, cy, cz) → Three.js world position.\n // Mirrors the display shader: sliceUV = worldPos.xz + 0.5, progress = worldPos.y + 0.5\n #cornerToWorld(cx: number, cy: number, cz: number): Vector3 {\n const N = this.#resolution;\n return new Vector3(cx / N - 0.5, cz / N - 0.5, cy / N - 0.5);\n }\n\n // Walk all 3 families of axis-aligned grid edges.\n // An edge is a Voronoi edge when its 4 surrounding voxels have ≥ 3 distinct labels.\n #extractEdges(pixels: Uint8Array): Array<{ p0: Vector3; p1: Vector3; label: number }> {\n const N = this.#resolution;\n const edges: Array<{ p0: Vector3; p1: Vector3; label: number }> = [];\n\n const check = (\n voxels: [number, number, number][],\n c0: [number, number, number],\n c1: [number, number, number],\n ) => {\n const labels: number[] = [];\n for (const [vx, vy, vz] of voxels) {\n const l = this.#getLabel(pixels, vx, vy, vz);\n if (l !== null) labels.push(l);\n }\n if (new Set(labels).size < 3) return;\n\n // Pick the most-represented neighboring label as tube color\n const counts = new Map<number, number>();\n for (const l of labels) counts.set(l, (counts.get(l) ?? 0) + 1);\n let best = labels[0], bestN = 0;\n for (const [l, c] of counts) if (c > bestN) { best = l; bestN = c; }\n\n edges.push({ p0: this.#cornerToWorld(...c0), p1: this.#cornerToWorld(...c1), label: best });\n };\n\n // Edges parallel to the Z axis (value/lightness axis in world Y)\n for (let cx = 0; cx <= N; cx++) {\n for (let cy = 0; cy <= N; cy++) {\n for (let k = 0; k < N; k++) {\n check(\n [[cx-1,cy-1,k],[cx,cy-1,k],[cx-1,cy,k],[cx,cy,k]],\n [cx, cy, k], [cx, cy, k+1],\n );\n }\n }\n }\n\n // Edges parallel to the X axis\n for (let cy = 0; cy <= N; cy++) {\n for (let cz = 0; cz <= N; cz++) {\n for (let k = 0; k < N; k++) {\n check(\n [[k,cy-1,cz-1],[k,cy,cz-1],[k,cy-1,cz],[k,cy,cz]],\n [k, cy, cz], [k+1, cy, cz],\n );\n }\n }\n }\n\n // Edges parallel to the Y axis\n for (let cx = 0; cx <= N; cx++) {\n for (let cz = 0; cz <= N; cz++) {\n for (let k = 0; k < N; k++) {\n check(\n [[cx-1,k,cz-1],[cx,k,cz-1],[cx-1,k,cz],[cx,k,cz]],\n [cx, k, cz], [cx, k+1, cz],\n );\n }\n }\n }\n\n return edges;\n }\n\n #buildGeometry(edges: Array<{ p0: Vector3; p1: Vector3; label: number }>): void {\n if (this.#tubeMesh) {\n this.#displayScene.remove(this.#tubeMesh);\n this.#tubeMesh.geometry.dispose();\n this.#tubeMesh = null;\n }\n if (this.#nodeMesh) {\n this.#displayScene.remove(this.#nodeMesh);\n this.#nodeMesh.geometry.dispose();\n this.#nodeMesh = null;\n }\n if (edges.length === 0) return;\n\n const tubeGeo = new CylinderGeometry(this.#tubeRadius, this.#tubeRadius, 1, this.#tubeSegments);\n const nodeGeo = new SphereGeometry(this.#tubeRadius, this.#tubeSegments, this.#tubeSegments >> 1);\n const dummy = new Object3D();\n const UP = new Vector3(0, 1, 0);\n const dir = new Vector3();\n const color = new Color();\n\n this.#tubeMesh = new InstancedMesh(tubeGeo, this.#tubeMaterial, edges.length);\n const nodeMap = new Map<string, { pos: Vector3; label: number }>();\n\n let validCount = 0;\n for (let i = 0; i < edges.length; i++) {\n const { p0, p1, label } = edges[i];\n dir.copy(p1).sub(p0);\n const len = dir.length();\n if (len < 1e-7) continue;\n\n dummy.position.copy(p0).add(p1).multiplyScalar(0.5);\n dummy.scale.set(1, len, 1);\n dummy.quaternion.setFromUnitVectors(UP, dir.divideScalar(len));\n dummy.updateMatrix();\n this.#tubeMesh.setMatrixAt(validCount, dummy.matrix);\n\n color.setRGB(((label >> 16) & 0xff) / 255, ((label >> 8) & 0xff) / 255, (label & 0xff) / 255);\n this.#tubeMesh.setColorAt(validCount, color);\n validCount++;\n\n const k0 = `${p0.x.toFixed(5)},${p0.y.toFixed(5)},${p0.z.toFixed(5)}`;\n const k1 = `${p1.x.toFixed(5)},${p1.y.toFixed(5)},${p1.z.toFixed(5)}`;\n if (!nodeMap.has(k0)) nodeMap.set(k0, { pos: p0, label });\n if (!nodeMap.has(k1)) nodeMap.set(k1, { pos: p1, label });\n }\n\n this.#tubeMesh.count = validCount;\n this.#tubeMesh.instanceMatrix.needsUpdate = true;\n if (this.#tubeMesh.instanceColor) this.#tubeMesh.instanceColor.needsUpdate = true;\n this.#displayScene.add(this.#tubeMesh);\n\n // Sphere caps at every junction so tubes connect cleanly\n const nodes = Array.from(nodeMap.values());\n this.#nodeMesh = new InstancedMesh(nodeGeo, this.#tubeMaterial, nodes.length);\n dummy.scale.set(1, 1, 1);\n dummy.quaternion.set(0, 0, 0, 1);\n for (let i = 0; i < nodes.length; i++) {\n const { pos, label } = nodes[i];\n dummy.position.copy(pos);\n dummy.updateMatrix();\n this.#nodeMesh.setMatrixAt(i, dummy.matrix);\n color.setRGB(((label >> 16) & 0xff) / 255, ((label >> 8) & 0xff) / 255, (label & 0xff) / 255);\n this.#nodeMesh.setColorAt(i, color);\n }\n this.#nodeMesh.instanceMatrix.needsUpdate = true;\n if (this.#nodeMesh.instanceColor) this.#nodeMesh.instanceColor.needsUpdate = true;\n this.#displayScene.add(this.#nodeMesh);\n }\n\n #rebuild(): void {\n this.#computeAtlas();\n const res = this.#resolution;\n const pixels = new Uint8Array(res * res * res * 4);\n this.#renderer.readRenderTargetPixels(this.#atlasTarget, 0, 0, res, res * res, pixels);\n const edges = this.#extractEdges(pixels);\n this.#buildGeometry(edges);\n this.#paint();\n }\n\n #updateCamera(): void {\n const x = this.#zoom * Math.sin(this.#yaw) * Math.cos(this.#pitch);\n const y = this.#zoom * Math.sin(this.#pitch);\n const z = this.#zoom * Math.cos(this.#yaw) * Math.cos(this.#pitch);\n this.#displayCamera.position.set(x, y, z);\n this.#displayCamera.lookAt(0, 0, 0);\n }\n\n #paint(): void {\n if (this.#animationFrame !== null) cancelAnimationFrame(this.#animationFrame);\n this.#animationFrame = requestAnimationFrame(() => {\n this.#renderer.render(this.#displayScene, this.#displayCamera);\n });\n }\n\n #initControls(): void {\n const el = this.#renderer.domElement;\n el.addEventListener(\"pointerdown\", (e) => {\n this.#dragStart = { x: e.clientX, y: e.clientY, yaw: this.#yaw, pitch: this.#pitch };\n el.setPointerCapture(e.pointerId);\n });\n el.addEventListener(\"pointermove\", (e) => {\n if (!this.#dragStart) return;\n const dx = e.clientX - this.#dragStart.x;\n const dy = e.clientY - this.#dragStart.y;\n this.#yaw = this.#dragStart.yaw - dx * 0.005;\n this.#pitch = Math.max(-Math.PI / 2.1, Math.min(Math.PI / 2.1,\n this.#dragStart.pitch + dy * 0.005));\n this.#updateCamera();\n this.#paint();\n });\n el.addEventListener(\"pointerup\", () => { this.#dragStart = null; });\n el.addEventListener(\"pointercancel\", () => { this.#dragStart = null; });\n el.addEventListener(\"wheel\", (e) => {\n e.preventDefault();\n this.#zoom = Math.max(0.2, Math.min(5, this.#zoom + e.deltaY * 0.001));\n this.#updateCamera();\n this.#paint();\n }, { passive: false });\n }\n\n // ── Public API ─────────────────────────────────────────────────────────────\n\n get canvas(): HTMLCanvasElement { return this.#renderer.domElement; }\n get width() { return this.#width; }\n get height() { return this.#height; }\n\n resize(width: number, height: number | null = null): void {\n this.#width = width;\n this.#height = height ?? width;\n this.#renderer.setSize(this.#width, this.#height);\n this.#displayCamera.aspect = this.#width / this.#height;\n this.#displayCamera.updateProjectionMatrix();\n this.#paint();\n }\n\n destroy(): void {\n if (this.#animationFrame !== null) {\n cancelAnimationFrame(this.#animationFrame);\n this.#animationFrame = null;\n }\n this.#paletteTexture.dispose();\n this.#atlasTarget.dispose();\n this.#computeMaterial.dispose();\n this.#tubeMaterial.dispose();\n this.#tubeMesh?.geometry.dispose();\n this.#nodeMesh?.geometry.dispose();\n this.#renderer.dispose();\n this.#renderer.domElement.remove();\n }\n\n // ── Palette ────────────────────────────────────────────────────────────────\n\n set palette(palette: ColorList) {\n this.#palette = palette;\n this.#paletteTexture = paletteToTexture(palette);\n this.#rebuild();\n }\n get palette() { return this.#palette; }\n\n setColor(color: ColorString, index: number): void {\n if (index < 0 || index >= this.#palette.length) throw new Error(`Index ${index} out of range`);\n this.#palette[index] = color;\n this.#paletteTexture = paletteToTexture(this.#palette);\n this.#rebuild();\n }\n\n // ── Shader properties — all trigger a full rebuild ─────────────────────────\n\n set colorModel(model: SupportedColorModels) { this.#colorModel = model; this.#rebuild(); }\n get colorModel() { return this.#colorModel; }\n\n set distanceMetric(metric: DistanceMetric) { this.#distanceMetric = metric; this.#rebuild(); }\n get distanceMetric() { return this.#distanceMetric; }\n\n set isPolar(value: boolean) { this.#isPolar = value; this.#rebuild(); }\n get isPolar() { return this.#isPolar; }\n\n set invertLightness(value: boolean) { this.#invertLightness = value; this.#rebuild(); }\n get invertLightness() { return this.#invertLightness; }\n\n set showRaw(value: boolean) { this.#showRaw = value; this.#rebuild(); }\n get showRaw() { return this.#showRaw; }\n\n // ── Orbit — no recomputation ───────────────────────────────────────────────\n\n set yaw(value: number) { this.#yaw = value; this.#updateCamera(); this.#paint(); }\n get yaw() { return this.#yaw; }\n\n set pitch(value: number) {\n this.#pitch = Math.max(-Math.PI / 2.1, Math.min(Math.PI / 2.1, value));\n this.#updateCamera(); this.#paint();\n }\n get pitch() { return this.#pitch; }\n\n set zoom(value: number) {\n this.#zoom = Math.max(0.2, Math.min(5, value));\n this.#updateCamera(); this.#paint();\n }\n get zoom() { return this.#zoom; }\n}\n"],"names":["shaderSRGB2RGB","shaderOKLab","shaderHSL2RGB","shaderHSV2RGB","shaderLCH2RGB","shaderDeltaE","shaderClosestColor","fragmentShader","vertexShader","paletteToTexture","palette","data","color","c","Color","texture","DataTexture","RGBAFormat","FloatType","ClampToEdgeWrapping","NearestFilter","randomPalette","size","PaletteViz","#palette","#width","#height","#pixelRatio","#position","#axis","#colorModel","#distanceMetric","#isPolar","#invertLightness","#showRaw","#axisMap","#colorModelMap","#distanceMetricMap","#texture","#uniforms","#material","#geometry","#mesh","#renderer","#camera","#scene","#animationFrame","#container","width","height","pixelRatio","container","colorModel","distanceMetric","isPolar","axis","position","invertLightness","showRaw","ShaderMaterial","#initThree","Scene","OrthographicCamera","WebGLRenderer","PlaneGeometry","Mesh","#paint","index","indexOrColor","value","model","metric","computeVertShader3D","computeFragShader3D","displayVertShader3D","displayFragShader3D","PaletteViz3D","#slices","#sliceResolution","#sliceOpacity","#yaw","#pitch","#zoom","#paletteTexture","#computeUniforms","#computeMaterial","#computeScene","#computeCamera","#atlasTarget","#displayUniforms","#displayMaterial","#slabMeshes","#displayScene","#displayCamera","#dragStart","yaw","pitch","zoom","slices","sliceResolution","sliceOpacity","#initControls","#computeAtlas","#invalidate","#updateCamera","x","y","z","N","mesh","i","WebGLRenderTarget","LinearFilter","DoubleSide","slabH","PerspectiveCamera","BoxGeometry","el","dx","dy","m","PaletteViz3DVoronoi","#resolution","#tubeRadius","#tubeSegments","#tubeMesh","#nodeMesh","#tubeMaterial","resolution","tubeRadius","tubeSegments","#rebuild","res","AmbientLight","dirLight","DirectionalLight","MeshStandardMaterial","#getLabel","pixels","ix","iy","iz","sx","sy","offset","#cornerToWorld","cx","cy","cz","Vector3","#extractEdges","edges","check","voxels","c0","c1","labels","vx","vy","vz","l","counts","best","bestN","k","#buildGeometry","tubeGeo","CylinderGeometry","nodeGeo","SphereGeometry","dummy","Object3D","UP","dir","InstancedMesh","nodeMap","validCount","p0","p1","label","len","k0","k1","nodes","pos"],"mappings":"yQAAA,MAAAA,EAAe;AAAA;AAAA;AAAA;AAAA,ECAfC,EAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GCAfC,EAAe;AAAA;AAAA;AAAA,GCAfC,EAAe;AAAA;AAAA;AAAA;AAAA,GCAfC,EAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,ECAfC,EAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAA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"}
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "palette-shader",
3
+ "version": "0.1.0",
4
+ "description": "Dependency-free WebGL2 shader that maps any colour palette across perceptual colour spaces — OKHsv, OKHsl, OKLCH and more.",
5
+ "keywords": [
6
+ "color", "colour", "palette", "shader", "webgl", "webgl2",
7
+ "oklab", "oklch", "okhsv", "okhsl", "deltaE", "visualization", "colour-science"
8
+ ],
9
+ "author": "David Aerne <meodai@gmail.com>",
10
+ "license": "MIT",
11
+ "homepage": "https://github.com/meodai/color-palette-shader#readme",
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "git+https://github.com/meodai/color-palette-shader.git"
15
+ },
16
+ "bugs": {
17
+ "url": "https://github.com/meodai/color-palette-shader/issues"
18
+ },
19
+ "type": "module",
20
+ "main": "./dist/palette-shader.umd.cjs",
21
+ "module": "./dist/palette-shader.js",
22
+ "types": "./dist/palette-shader.d.ts",
23
+ "exports": {
24
+ ".": {
25
+ "types": "./dist/palette-shader.d.ts",
26
+ "import": "./dist/palette-shader.js",
27
+ "require": "./dist/palette-shader.umd.cjs"
28
+ }
29
+ },
30
+ "files": [
31
+ "dist",
32
+ "src"
33
+ ],
34
+ "sideEffects": false,
35
+ "workspaces": [
36
+ "demo"
37
+ ],
38
+ "scripts": {
39
+ "dev": "npm run dev -w demo",
40
+ "build": "vite build",
41
+ "typecheck": "tsc --noEmit",
42
+ "preview": "npm run preview -w demo"
43
+ },
44
+ "devDependencies": {
45
+ "typescript": "^5.4.5",
46
+ "vite": "^7.0.0",
47
+ "vite-plugin-dts": "^4.5.4"
48
+ }
49
+ }