<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);
	console.log(sRGBtoXYZ(...degamma(0.5, 0.5, 0.5)));
}

// http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html

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 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;
}

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 lrgb = XYZtoSRGB(vec3(x, y, z) * 1.1);
	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;
}`;


Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.