Public
Edited
Jan 18, 2023
2 forks
2 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
predefinedComplex
Type Table, then Shift-Enter. Ctrl-space for more options.

Insert cell
renderPalette = function (
composer,
defaultAmplitude = 1,
defaultPalette = 0,
components = "x"
) {
const { GPUProgram, FLOAT, INT } = gpuio;
return new GPUProgram(composer, {
name: "renderPalette",
fragmentShader: `
in vec2 v_uv;
uniform sampler2D u_state;
uniform float u_amplitude;
uniform int u_palette;
out vec4 out_color;

const vec3 table[32] = vec3[32](vec3(0.5,0.5,0.5),vec3(0.5,0.5,0.5),vec3(1.0,1.0,1.0),vec3(1.0,1.0,1.0),
vec3(0.5,0.5,0.5),vec3(0.5,0.5,0.5),vec3(1.0,1.0,1.0),vec3(0.0,0.33,0.67),
vec3(0.5,0.5,0.5),vec3(0.5,0.5,0.5),vec3(1.0,1.0,1.0),vec3(0.0,0.10,0.20),
vec3(0.5,0.5,0.5),vec3(0.5,0.5,0.5),vec3(1.0,1.0,1.0),vec3(0.3,0.20,0.20),
vec3(0.5,0.5,0.5),vec3(0.5,0.5,0.5),vec3(1.0,1.0,0.5),vec3(0.8,0.90,0.30),
vec3(0.5,0.5,0.5),vec3(0.5,0.5,0.5),vec3(1.0,0.7,0.4),vec3(0.0,0.15,0.20),
vec3(0.5,0.5,0.5),vec3(0.5,0.5,0.5),vec3(2.0,1.0,0.0),vec3(0.5,0.20,0.25),
vec3(0.8,0.5,0.4),vec3(0.2,0.4,0.2),vec3(2.0,1.0,1.0),vec3(0.0,0.25,0.25)
);
vec3 pal( in float t, in int i )
{
vec3 a = table[i*4];
vec3 b = table[i*4+1];
vec3 c = table[i*4+2];
vec3 d = table[i*4+3];
return a + b*cos( 3.1416*(c*t+d) );
}
void main() {
float val = u_amplitude * texture(u_state, v_uv).${components} ;
vec3 col = pal(val, u_palette);
out_color = vec4(col, 1);
}
`,
uniforms: [
{
name: "u_amplitude",
value: defaultAmplitude,
type: FLOAT
},
{
name: "u_palette",
value: defaultPalette,
type: INT
}
]
});
}
Insert cell
gpuio = require("gpu-io")
Insert cell
d3 = require("d3")
Insert cell
Insert cell
Insert cell
// Touch pad
canvasTouchPad = {
const { width, height, realRange, imageRange, defaultReal, defaultImage } =
touchPadSetup;

const canvas = document.createElement("canvas");
(canvas.width = width), (canvas.height = height);
const ctx = canvas.getContext("2d");

const scaleX = d3.scaleLinear().range(realRange).domain([0, width]).nice(),
scaleY = d3.scaleLinear().range(imageRange).domain([height, 0]).nice();

clear();
drawPoint(scaleX.invert(defaultReal), scaleY.invert(defaultImage));

canvas.addEventListener("mousemove", onMouseMove, false);
canvas.addEventListener("click", onClick, false);

viewof randomSelect.addEventListener("input", () => {
console.log("Random Select Button is clicked.");
const lst = predefinedComplex.map((e) => e);
d3.shuffle(lst);
const select = lst[0];
console.log(select);

clear();
drawPoint(scaleX.invert(select.real), scaleY.invert(select.image));
});

return canvas;

/**
* Handle mouseMove events
*/
function onMouseMove(e) {
if (e.buttons > 0) {
clear();
drawPoint(0, 0, e);
}
}

/**
* Handle mouse click events
*/
function onClick(e) {
const { offsetX: x, offsetY: y } = e;
clear();
drawPoint(x, y);
}

/**
* Clear the canvas
*/
function clear() {
ctx.fillStyle = "#367a95";
ctx.fillRect(0, 0, canvas.width, canvas.height);

ctx.fillStyle = d3.color(d3.hsl(216, 0.2, 0.3)).formatHex();
ctx.fillRect(0, 0, width / 2, height / 2);

predefinedComplex.map(({ real, image }) => {
drawPoint(
scaleX.invert(real),
scaleY.invert(image),
undefined,
"#f0f0f0a0",
"notUpdate"
);
});
}

/**
* Draw point on x, y;
* the x and y will be override if e exists.
*/
function drawPoint(x, y, e, color, update = "update") {
if (e) {
x = e.offsetX;
y = e.offsetY;
}
ctx.fillStyle = color ? color : "red";
ctx.beginPath();
ctx.arc(x, y, width / 50, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fill();

if (update === "update") {
Object.assign(targetComplex, {
real: scaleX(x),
image: scaleY(y),
needsCompute: true
});

const pa = document.getElementById("ParamsArea1");
if (pa) {
pa.innerHTML = `
real: ${targetComplex.real.toFixed(4)},
image: ${targetComplex.image.toFixed(4)}
`;
}
}
}
}
Insert cell
predefinedComplex = {
return [
{ real: -0.23, image: 0.65 },
{ real: 0.275, image: 0.485 },
{ real: -0.54, image: -0.5 },
{ real: -0.705, image: -0.27 },
{ real: 0.38, image: -0.23 },
{ real: 0.285, image: -0.47 },
{ real: 0.35, image: 0.09 },
{ real: -0.57, image: 0.465 },
{ real: -0.735, image: 0 },
{ real: -0.07, image: -0.665 },
{ real: -0.3, image: -0.63 },
{ real: 0.06, image: 0.63 },
{ real: -0.715, image: 0.245 },
{ real: 0.1325, image: -0.59 },
{ real: -0.3888, image: 0.595 },
{ real: -0.0887, image: 0.655 },
{ real: 0.3987, image: 0.33 },
{ real: 0.16, image: 0.5867 },
{ real: -0.185, image: -0.6533 },
{ real: -0.42, image: -0.5867 },
{ real: 0.35, image: -0.08 },
{ real: -0.63, image: -0.3933 },
{ real: -0.795, image: 0.1467 },
{ real: -0.805, image: -0.16 },
{ real: 0.055, image: -0.64 },
{ real: 0.215, image: -0.5467 },
{ real: 0.345, image: -0.3733 },
{ real: -0.495, image: 0.5867 },
{ real: -0.885, image: 0.0133 },
{ real: -0.655, image: 0.3733 },
{ real: -0.7467, image: 0.1133 }
];
}
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more