Published
Edited
Feb 12, 2020
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
ni = 500 // number of grid points in x direction
Insert cell
nj = 500 // number of grid points in y direction
Insert cell
nt = 100 // number of time levels
Insert cell
gl = {
const glTris = twgl.getWebGLContext(canvas, {
antialias: false,
depth: false
});
twgl.addExtensionsToContext(glTris);
twgl.resizeCanvasToDisplaySize(glTris.canvas, window.devicePixelRatio || 1);
glTris.viewport(0, 0, glTris.canvas.width, glTris.canvas.height);
return glTris;
}
Insert cell
programInfo = {
const programInfo = twgl.createProgramInfo(gl, [vert, frag]);
gl.useProgram(programInfo.program);
return programInfo;
}
Insert cell
nverts = ni*nj
Insert cell
ntris = (ni-1)*(nj-1)*2
Insert cell
initBlock = {
const arrays = {
a_position: {numComponents: 2, data: grid},
a_val: {numComponents: 1, data: new Float32Array(values.buffer,0,nverts)},
indices: {numComponents: 3, data: indices}
};
const bufferInfo = twgl.createBufferInfoFromArrays(gl, arrays);
twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
const projectionMatrix = mat4.create();
mat4.ortho(projectionMatrix,-1,1, -1, 1, 0, 1.);
const cmap = new Uint8Array([158, 1, 66, 255, 185, 31, 72, 255, 209, 60, 75, 255, 228, 86, 73, 255, 240, 112, 74, 255, 248, 142, 83, 255, 252, 172, 99, 255, 253, 198, 118, 255, 254, 221, 141, 255, 254, 238, 163, 255, 251, 248, 176, 255, 241, 249, 171, 255, 224, 243, 160, 255, 200, 233, 159, 255, 169, 220, 162, 255, 137, 207, 165, 255, 105, 189, 169, 255, 78, 164, 176, 255, 66, 136, 181, 255, 74, 108, 174, 255, 94, 79, 162, 255]);
const cmapTex = twgl.createTexture(gl, {mag: gl.LINEAR, min:gl.LINEAR, src: cmap, width:21, height:1} );
const uniforms = {u_matrix: projectionMatrix, u_cmap: cmapTex};
twgl.setUniforms(programInfo, uniforms);
gl.drawElements(gl.TRIANGLES, ntris*3, gl.UNSIGNED_INT, 0);
}
Insert cell
updateValues = {
const arrays = {a_val: {numComponents: 1, data: new Float32Array(values.buffer,4*t*nverts,nverts)}};
const bufferInfo = twgl.createBufferInfoFromArrays(gl, arrays);
twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
gl.drawElements(gl.TRIANGLES, ntris*3, gl.UNSIGNED_INT, 0);
}
Insert cell
grid = {
const coords = new Float32Array(ni*nj*2);
let dx=2./(ni-1);
let dy=2./(nj-1);
let k = 0;
for (let j=0; j<nj; j++) {
for (let i=0; i<ni; i++) {
coords[k] = i*dx - 1.;
coords[k+1] = j*dy -1.;
k+=2;
}
}
return coords;
}
Insert cell
values = {
const vals = new Float32Array(ni*nj*nt);
let kval = 0;
for (let tt=0; tt<nt; tt++) {
let phase = tt/nt * 2. * Math.PI;
let kvert = 0;
for (let j=0; j<nj; j++) {
for (let i=0; i<ni; i++) {
let xnow = grid[kvert*2];
let ynow = grid[kvert*2 + 1];
let r = Math.sqrt(xnow*xnow + ynow*ynow);
vals[kval]=0.5*(1+Math.sin(5*r*Math.PI + phase));
kval++;
kvert++;
}
}
}
return vals;
}
Insert cell
indices = {
const inds = new Int32Array(ntris*3);
let k = 0;
for (let j=0; j<(nj-1); j++) {
for (let i=0; i<(ni-1); i++) {
let v0 = j*ni + i;
let v1 = v0 + 1;
let v2 = v1 + ni;
let v3 = v2 - 1;
inds[k] = v0;
inds[k+1] = v1;
inds[k+2] = v2;
inds[k+3] = v0;
inds[k+4] = v2;
inds[k+5] = v3;
k+=6;
}
}
return inds;
}
Insert cell
vert = `
attribute vec2 a_position;
attribute float a_val;

uniform mat4 u_matrix;

varying float v_val;

void main() {
gl_Position = u_matrix*vec4(a_position,0,1);

v_val = a_val;
}
`
Insert cell
frag = `
precision highp float;

uniform sampler2D u_cmap;

varying float v_val;

void main() {
gl_FragColor = texture2D(u_cmap, vec2(v_val,0.5));
}
`
Insert cell
twgl = require("https://cdn.jsdelivr.net/npm/twgl-base.js@4.8.2/dist/4.x/twgl.min.js")
Insert cell
glMatrix = import('gl-matrix@3')
Insert cell
mat4 = glMatrix.mat4
Insert cell
import {slider} from "@jashkenas/inputs"
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