Published
Edited
Nov 26, 2019
10 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
draw = {
gl.useProgram(program);
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.enableVertexAttribArray(a_vertex);
gl.vertexAttribPointer(a_vertex, 2, gl.FLOAT, false, 0, 0);
while (true) {
let t = now / 1000 % 10000;
gl.uniform1f(gl.getUniformLocation(program, "t"), t);
gl.uniform1f(gl.getUniformLocation(program, "contourSpacing"), contourSpacing);
gl.uniform1f(gl.getUniformLocation(program, "scale"), scale / 32.0 / 32.0);
gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);
yield t;
}
}
Insert cell
gl = {
const gl = canvas.getContext("webgl", {depth: false});
gl.getExtension('oes_standard_derivatives');
return gl;
}
Insert cell
fragmentShader = {
const shader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(shader, `
#extension GL_OES_standard_derivatives : enable
precision highp float;

const float pi = 3.14159265359;
const float width = ${canvas.width.toFixed(1)}; // TODO uniform?
const float height = ${canvas.height.toFixed(1)}; // TODO uniform?
const vec2 center = vec2(width, height) / 2.0;
uniform float t, contourSpacing, scale;

float value(float x, float y) {
return (${value});
}

vec3 cubehelix(vec3 c) {
float a = c.y * c.z * (1.0 - c.z);
float cosh = cos(c.x + pi / 2.0);
float sinh = sin(c.x + pi / 2.0);
return vec3(
(c.z + a * (1.78277 * sinh - 0.14861 * cosh)),
(c.z - a * (0.29227 * cosh + 0.90649 * sinh)),
(c.z + a * (1.97294 * cosh))
);
}

vec3 cubehelixDefault(float t) {
return cubehelix(vec3(mix(300.0 / 180.0 * pi, -240.0 / 180.0 * pi, t), 0.5, t));
}

vec3 cubehelixRainbow(float t) {
if (t < 0.0 || t > 1.0) t -= floor(t);
float ts = abs(t - 0.5);
return cubehelix(vec3((360.0 * t - 100.0) / 180.0 * pi, 1.5 - 1.5 * ts, 0.8 - 0.9 * ts));
}

float contourFunction (float f, float width, float feather) {
float w1 = width - feather * 0.5;
// Two slightly different options for the gradient magnitude. The first is a
// little faster, the second is a little more accurate. We use this to compute
// the required line width
//float d = fwidth(f);
float d = length(vec2(dFdx(f), dFdy(f)));

// Repeat the contour level every 1.0 units:
f = 0.5 - abs(mod(f, 1.0) - 0.5);

return smoothstep(d * w1, d * (w1 + feather), f);
}

void main(void) {
vec2 z = (gl_FragCoord.xy - center) * scale;
float f = value(z.x, z.y);
float contour = contourFunction(f / contourSpacing, 0.5, 0.75);
gl_FragColor = vec4(vec3(contour), 1.0);
}
`);
gl.compileShader(shader);
if (gl.getShaderParameter(shader, gl.COMPILE_STATUS)) return shader;
throw new Error(gl.getShaderInfoLog(shader));
}
Insert cell
vertexShader = {
const shader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(shader, `
attribute vec2 a_vertex;
void main(void) {
gl_Position = vec4(a_vertex, 0.0, 1.0);
}
`);
gl.compileShader(shader);
if (gl.getShaderParameter(shader, gl.COMPILE_STATUS)) return shader;
throw new Error(gl.getShaderInfoLog(shader));
}
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)) return program;
throw new Error(gl.getProgramInfoLog(program));
}
Insert cell
vertexBuffer = {
const buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, Float32Array.of(-1, -1, +1, -1, +1, +1, -1, +1), gl.STATIC_DRAW);
return buffer;
}
Insert cell
a_vertex = gl.getAttribLocation(program, "a_vertex")
Insert cell
height = 800
Insert cell
style = html`<style>

textarea.source {
display: block;
box-sizing: border-box;
width: calc(100% + 28px);
font: var(--mono_fonts);
min-height: 33px;
border: none;
padding: 6px 10px;
margin: 0 -14px;
background: rgb(247,247,249);
tab-size: 2;
resize: none;
}

textarea.source:focus {
outline: none;
}

</style>`
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