Published
Edited
Sep 16, 2019
2 forks
33 stars
Insert cell
Insert cell
viewof gl = {
const canvas = DOM.canvas(width, height);
canvas.value = canvas.getContext("webgl");
return canvas;
}
Insert cell
draw = {
gl.useProgram(program);
gl.enableVertexAttribArray(a_vertex);
gl.vertexAttribPointer(a_vertex, 2, gl.FLOAT, false, 0, 0);
gl.uniform1f(u_size, Math.max(viewof gl.width, viewof gl.height));
while (true) {
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, video);
gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);
yield;
}
}
Insert cell
fragmentShader = {
const shader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(shader, `
precision highp float;

uniform sampler2D u_image;
uniform float u_size;

void main() {
float x = gl_FragCoord.x / u_size;
float y = 1.0 - gl_FragCoord.y / u_size;
float px = 1.0 / u_size;
vec3 a0 = texture2D(u_image, vec2(x - px, y + px)).xyz;
vec3 a1 = texture2D(u_image, vec2(x, y + px)).xyz;
vec3 a2 = texture2D(u_image, vec2(x + px, y + px)).xyz;
vec3 a3 = texture2D(u_image, vec2(x - px, y)).xyz;
vec3 a5 = texture2D(u_image, vec2(x + px, y)).xyz;
vec3 a6 = texture2D(u_image, vec2(x - px, y - px)).xyz;
vec3 a7 = texture2D(u_image, vec2(x, y - px)).xyz;
vec3 a8 = texture2D(u_image, vec2(x + px, y - px)).xyz;
vec3 gx = -a0 + a2 - 2.0 * a3 + 2.0 * a5 - a6 + a8;
vec3 gy = -a0 - 2.0 * a1 - a2 + a6 + 2.0 * a7 + a8;
gl_FragColor = vec4(sqrt(gx * gx + gy * gy), 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
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
video = {
const video = document.createElement("div").appendChild(html`<video autoplay playsinline>`);
const stream = await navigator.mediaDevices.getUserMedia({
video: {width: {ideal: size}, height: {ideal: size}},
audio: false
});
yield video;
video.srcObject = stream;
video.play();
invalidation.then(() => stream.getTracks().forEach(t => t.stop()));
}
Insert cell
texture = {
const texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
return texture;
}
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
u_size = gl.getUniformLocation(program, "u_size")
Insert cell
a_vertex = gl.getAttribLocation(program, "a_vertex")
Insert cell
size = 512
Insert cell
height = width
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