<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;
}`;
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.