createCanvas(windowWidth, windowHeight);
colorMode(HSB, 360, 100, 100);
const bezierFunc = createBezierFromPoints([
[0,0.1], [0.4, 0.1],[0.2, 0.8],
[0.6, 0.9], [0.7, 0.925], [0.8, 0.9],
const range = [-10, 250];
const rangeW = range[1] - range[0];
const colorBarH = windowHeight / 4;
const graphH = (windowHeight - colorBarH) * 0.8;
const graphStepW = windowWidth / rangeW + 1;
const y = windowHeight - colorBarH;
for (let i = 0; i < rangeW; i++) {
const x = windowWidth / rangeW * i;
fill(range[1] - i, 100, 100);
rect(x, y, graphStepW, colorBarH);
const bx = windowWidth / rangeW * (range[1] - 240);
line(bx, 0, bx, windowHeight);
const gx = windowWidth / rangeW * (range[1] - 120);
line(gx, 0, gx, windowHeight);
const rx = windowWidth / rangeW * (range[1] - 0);
line(rx, 0, rx, windowHeight);
const substance = [], light = [], reflection = [];
for (let i = 0; i < rangeW; i++) {
light.push(noise(i / rangeW) + 0.25);
substance.push(bezierFunc(i / rangeW));
reflection.push(light[i] * substance[i]);
drawGraph(light, [255, 255, 128], 1);
drawGraph(substance, [255, 128, 255], 1);
drawGraph(reflection, [256, 256, 256], 4);
function drawGraph(data, color, w) {
stroke(...color); strokeWeight(w);
for (let i = 0; i < data.length; i++) {
const x = windowWidth * i / data.length;
const py = y - data[i] * graphH;
function createBezierFromPoints(pts, resolution = 240) {
for (let pi = 0; pi < pts.length / 4; pi++) {
for (let ti = 0; ti <= resolution * 10; ti++) {
const t = ti / (resolution * 10);
const x = pow(1 - t, 3) * pts[pi * 3][0] + 3 * pow(1 - t, 2) * t * pts[pi * 3 + 1][0] +
3 * (1 - t) * pow(t, 2) * pts[pi * 3 + 2][0] + pow(t, 3) * pts[pi * 3 + 3][0];
const y = pow(1 - t, 3) * pts[pi * 3][1] + 3 * pow(1 - t, 2) * t * pts[pi * 3 + 1][1] +
3 * (1 - t) * pow(t, 2) * pts[pi * 3 + 2][1] + pow(t, 3) * pts[pi * 3 + 3][1];
if (x >= i / resolution) {
let ti = floor(t * buff.length);
let tr = t * buff.length - ti;
if (ti >= buff.length - 1) {
return buff[buff.length - 1];
return buff[ti] * (1 - tr) + buff[ti + 1] * tr;