Published
Edited
Nov 24, 2019
5 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
vertexShader = {
const shader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(shader, `
precision highp float;

const float PI = 3.14159265359;

const float alpha = ${alpha};

attribute vec2 position;
attribute vec3 color;

varying highp vec3 vColor;

void main() {
float x1, x2 = position.x;
float y1, y2 = position.y;

vColor = color;
for (int i = 0; i < ${iterations}; i++) {
x1 = x2, y1 = y2;
x2 = x1 * cos(alpha) - (y1 - x1*x1)*sin(alpha);
y2 = x1 * sin(alpha) + (y1 - x1*x1)*cos(alpha);
}
gl_Position = vec4(x2, y2, 0.0, 1.0);
gl_PointSize = 2.0;
}
`);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) throw gl.getShaderInfoLog(shader);
invalidation.then(() => gl.deleteShader(shader));
return shader;
}
Insert cell
draw = {
setup;
gl.drawArrays(gl.POINTS, 0, n);
}
Insert cell
Insert cell
Insert cell
positionData = Array.from({length: n}).map(() => ({
x: Math.random() * 2 - 1,
y: Math.random() * 2 - 1
}));
Insert cell
Insert cell
vertexBuffer = {
const array = new Float32Array(positionData.flatMap(p => [p.x, p.y]));
const buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, array, gl.STATIC_DRAW);
invalidation.then(() => gl.deleteBuffer(buffer));
return buffer;
}
Insert cell
Insert cell
colorData = {
const nCols = 100;
const nRows = 100;
const cScale = d3.scaleSequentialQuantile(d3.range(nCols*nRows), d3.interpolateTurbo)
return positionData.flatMap(p => {
const c = Math.floor((p.x + 1)/2*nCols);
const r = Math.floor((p.y + 1)/2*nRows);
const idx = r*nRows + c
const color = d3.color(cScale(idx))
return [color.r/255, color.g/255, color.b/255]
})
}
Insert cell
colorBuffer = {
const array = new Float32Array(colorData);
const buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, array, gl.STATIC_DRAW);
invalidation.then(() => gl.deleteBuffer(buffer));
return buffer;
}
Insert cell
Insert cell
fragmentShader = {
const shader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(shader, `
precision highp float;
varying highp vec3 vColor;
void main() {

gl_FragColor = vec4(vColor, 1.0);
}
`);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) throw gl.getShaderInfoLog(shader);
invalidation.then(() => gl.deleteShader(shader));
return shader;
}
Insert cell
Insert cell
program = {
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) throw gl.getProgramInfoLog(program);
invalidation.then(() => gl.deleteProgram(program));
return program;
}
Insert cell
Insert cell
setup = {
const a_position = gl.getAttribLocation(program, "position");
gl.useProgram(program);
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.vertexAttribPointer(a_position, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(a_position);
const a_color = gl.getAttribLocation(program, "color");
gl.useProgram(program);
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
gl.vertexAttribPointer(a_color, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(a_color);
}
Insert cell
Insert cell
n = Math.pow(2, 19)
Insert cell
Insert cell
height = width
Insert cell
width = 500
Insert cell
import {slider} from "@jashkenas/inputs"
Insert cell
d3 = require("d3@5")
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