<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.11.2/p5.js" integrity="sha512-U9A2hkdqQwJaC2PgtQYCAZl6OkYhJOvF86X9ibqKw1bsYnn3txJAyeRQzYwSD0qRgBUzKXdhzGUGIYzuoh4JEA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.11.2/addons/p5.sound.js" integrity="sha512-TU9AWtV5uUZPX8dbBAH8NQF1tSdigPRRT82vllAQ1Ke28puiqLA6ZVKxtUGlgrH6yWFnkKy+sE6luNEGH9ar0A==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
body {margin:0px; padding:0px; overflow: hidden}
#code {
position: absolute;
top: 0;
left: 0;
font-family: monospace;
z-index: 1000;
color: #ffffff;
padding: 8px;
white-space: pre-wrap;
font-size:10px;
}
let program;
function setup() {
pixelDensity(1);
smooth();
createCanvas(windowWidth, windowHeight,WEBGL);
program = createShader(vert,frag);
rgb = [0.5, 0.5, 0.5];
xyz = sRGBtoXYZ(...degamma(...rgb));
//lab = sRGBtoLAB(...degamma(0.5,0.5,0.5));
console.log("xyz", xyz);
console.log("rgb", XYZtoSRGB(...xyz));
lab = XYZtoLAB(...xyz);
console.log("lab", lab);
console.log("xyz", LABtoXYZ(...lab));
//console.log(lab);
//console.log(gamma(...LABtoSRGB(...lab)));
}
function XYZtoSRGB(x,y,z) {
return [
3.2404542 * x -1.5371385 * y -0.4985314 * z,
-0.9692660 * x + 1.8760108 * y + 0.0415560 * z,
0.0556434 * x -0.2040259 * y + 1.0572252 * z
];
}
function sRGBtoXYZ(x,y,z) {
return [
0.4124564 * x + 0.3575761 * y + 0.1804375 * z,
0.2126729 * x + 0.7151522 * y + 0.0721750 * z,
0.0193339 * x + 0.1191920 * y + 0.9503041 * z
];
}
function LABtoXYZ(l,a,b){
const EPSILON = 216.0 / 24389.0;
const KAPPA = 24389.0 / 27.0;
const whitePoint = {x:0.9504492182750991, y:1.0, z:1.0889166484304715}; // D65
const fy = (l + 16.0) / 116.0;
const fx = a / 500.0 + fy;
const fz = fy - b / 200.0;
const rx = pow(fx, 3.0) > EPSILON ? pow(fx, 3.0) : (fx * 116.0 - 16.0) / KAPPA;
const ry = l > KAPPA * EPSILON ? pow((l + 16.0) / 116.0, 3.0) : l / KAPPA;
const rz = pow(fz, 3.0) > EPSILON ? pow(fz, 3.0) : (fz * 116.0 - 16.0) / KAPPA;
return [whitePoint.x * rx, whitePoint.y * ry, whitePoint.z * rz]
}
//http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_Lab.html
function XYZtoLAB(x, y, z){
const EPSILON = 216.0 / 24389.0;
const KAPPA = 24389.0 / 27.0;
const whitePoint = {x:0.9504492182750991, y:1.0, z:1.0889166484304715}; // D65
const xr = x / whitePoint.x;
const yr = y / whitePoint.y;
const zr = z / whitePoint.z;
const fx = (xr > EPSILON) ? Math.pow(xr, 1.0/3.0) : (KAPPA * xr + 16.0)/116.0;
const fy = (yr > EPSILON) ? Math.pow(yr, 1.0/3.0) : (KAPPA * yr + 16.0)/116.0;
const fz = (zr > EPSILON) ? Math.pow(zr, 1.0/3.0) : (KAPPA * zr + 16.0)/116.0;
return [(116.0 * fy) - 16.0, 500.0 * (fx - fy), 200.0 * (fy - fz)]
}
function LABtoSRGB(l,a,b) {
return XYZtoSRGB(...LABtoXYZ(l,a,b));
}
function sRGBtoLAB(x,y,z) {
return XYZtoLAB(...sRGBtoXYZ(x,y,z));
}
function degamma(r,g,b) {
return [pow(max(0, r), 2.2), pow(max(0, g), 2.2), pow(max(0, b), 2.2)];
}
function gamma(r,g,b) {
return [pow(max(0, r), 1/2.2), pow(max(0, g), 1/2.2), pow(max(0, b), 1/2.2)];
}
function draw() {
const margin = 32;
const side = min(width, height) - margin * 2;
background(0);
fill(255);
shader(program);
const loopLen = 360;
program.setUniform("mouseY", (mouseY - (height - side) * 0.5) / side);
program.setUniform("rect", [(width - side) / 2, (height - side) / 2, side, side]);
rect(-side * 0.5, -side* 0.5, side, side);
resetShader();
}
const vert=`
#ifdef GL_ES
precision highp float;
precision highp int;
#endif
attribute vec3 aPosition;
uniform mat4 uModelViewMatrix;
uniform mat4 uProjectionMatrix;
uniform mat3 uNormalMatrix;
void main() {
gl_Position = uProjectionMatrix * uModelViewMatrix * vec4(aPosition, 1.0);
}`;
const frag=`
#ifdef GL_ES
precision highp float;
#endif
uniform float mouseY;
uniform vec4 rect;
mat3 transpose(mat3 m) {
return mat3(
m[0][0], m[1][0], m[2][0],
m[0][1], m[1][1], m[2][1],
m[0][2], m[1][2], m[2][2]);
}
mat2 inv(mat2 m) {
float a = m[0][0];
float b = m[1][0];
float c = m[0][1];
float d = m[1][1];
float det = (a * d - b * c);
if (det != 0.0) {
return mat2(d, -b, -c, a) / det ;
} else {
return mat2(0.0, 0.0, 0.0, 0.0);
}
}
vec3 XYZtoSRGB(vec3 xyz) {
return transpose(mat3(
3.2404542, -1.5371385, -0.4985314,
-0.9692660, 1.8760108, 0.0415560,
0.0556434, -0.2040259, 1.0572252)
) * xyz;
}
vec3 LABtoXYZ(vec3 lab){
float EPSILON = 216.0 / 24389.0;
float KAPPA = 24389.0 / 27.0;
vec3 whitePoint = vec3(0.9504492182750991, 1.0, 1.0889166484304715); // D65
float fy = (lab.x + 16.0) / 116.0;
float fx = lab.y / 500.0 + fy;
float fz = fy - lab.z / 200.0;
float rx = pow(max(0.0, fx), 3.0) > EPSILON ? pow(max(0.0, fx), 3.0) : (fx * 116.0 - 16.0) / KAPPA;
float ry = lab.x > KAPPA * EPSILON ? pow((lab.x + 16.0) / 116.0, 3.0) : lab.x / KAPPA;
float rz = pow(max(0.0, fz), 3.0) > EPSILON ? pow(max(0.0, fz), 3.0) : (fz * 116.0 - 16.0) / KAPPA;
return vec3(whitePoint.x * rx, whitePoint.y * ry, whitePoint.z * rz);
}
void main(void)
{
vec2 crd = ((gl_FragCoord.xy - rect.xy) / rect.zw - vec2(0.5)) * 2.0;
float px = 1.0 / max(rect.z, rect.w);
float sqrt3 = sqrt(3.0);
float yTh = clamp((1.0 - mouseY) * 2.0, 0.0, 1.0);
float x = 0.0, y = 0.0, z = 0.0;
if (crd.x < 0.0) {
vec2 lCrd = crd - vec2(-sqrt3 * 0.5, -0.5);
mat2 mat = inv(mat2(sqrt3, 0.0, -1.0, 2.0) * 0.5);
lCrd = mat * lCrd;
x = lCrd.x;
y = lCrd.y;
} else {
vec2 lCrd = crd - vec2(0.0, -1.0);
mat2 mat = inv(mat2(sqrt3, 0.0, 1.0, 2.0) * 0.5);
lCrd = mat * lCrd;
x = 1.0;
z = lCrd.x;
y = lCrd.y;
}
if (y > yTh) {
vec2 lCrd = crd - vec2(-sqrt3 * 0.5, -0.5 + yTh);
mat2 mat = inv(mat2(sqrt3, sqrt3, -1.0, 1.0) * 0.5);
lCrd = mat * lCrd;
x = lCrd.x;
y = yTh;
z = lCrd.y;
}
vec3 xyz = LABtoXYZ(vec3(y * 100.0, (x - 0.5) * 256.0, (z - 0.5) * 256.0));
vec3 lrgb = XYZtoSRGB(xyz);
vec3 rgb = pow(clamp(lrgb, vec3(0.0), vec3(1.0)), vec3(1.0/2.2));
vec4 color = vec4(rgb, 1.0);
float mx = max(x, max(y, z));
float mn = min(x, min(y, z));
color.rgb = mix(color.rgb, vec3(0.0), smoothstep(0.0, px, -mn));
color.rgb = mix(color.rgb, vec3(0.0), smoothstep(0.0, px, mx - 1.0));
gl_FragColor=color;
}`;
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.