Published unlisted
Edited
Oct 22, 2021
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
//pitch = (((now / 1000) % 10000) * 180) / Math.PI
viewof pitch = Range([0, 90], { value: 80, label: 'Camera pitch' })
Insert cell
Insert cell
createREGL = require('regl')
Insert cell
{
fov;
regl.poll();
regl.clear({ color: [1, 1, 1, 1] });
drawLine({
positionBuffer,
count: positions.length,
lineWidth,
lineOpacity,
antialiasWidth,
projectionView
});
}
Insert cell
positions = {
const n = 10;
return [...Array(n).keys()].map(i => [
i / (n - 1) - 0.5,
Math.random() * 2 - 1
]);
}
Insert cell
positionBuffer = regl.buffer(positions)
Insert cell
drawLine = regl({
vert: `
precision highp float;
attribute vec2 curPosition, nextPosition, line;
uniform float aspect, width;
uniform mat4 projectionView;
varying float y;
// https://github.com/substack/screen-projected-lines
// Copyright (c) 2016, James Halliday
// BSD 2-Clause License
vec4 lineOffset (vec4 p, vec4 n, float direction, float aspect) {
vec2 sp = p.xy/p.w*vec2(aspect,1);
vec2 sn = n.xy/n.w*vec2(aspect,1);
vec2 dir = normalize(sn-sp);
vec2 norm = dir.yx*vec2(-1.0/aspect,1);
return vec4(direction*norm,0,0);
}
void main () {
vec4 p1 = projectionView * vec4(curPosition, 0, 1);
vec4 p2 = projectionView * vec4(nextPosition, 0, 1);
//p1 /= p1.w;
//p2 /= p2.w;
vec4 position = mix(p1, p2, line.x);
vec4 offset = lineOffset(p1, p2, line.y, aspect);

y = line.y;
gl_Position = position + offset * width;
}`,
frag: `
#extension GL_OES_standard_derivatives : enable
precision mediump float;
uniform float antialiasWidth, alpha;
varying float y;
void main () {
float gradient = length(vec2(dFdx(y), dFdy(y)));
gradient *= antialiasWidth;
float antialias = min(1.0, (1.0 - abs(y)) / gradient);
gl_FragColor = alpha * antialias * vec4(1, 0, 0, 1);
}`,
attributes: {
curPosition: (ctx, props) => ({
buffer: props.positionBuffer,
offset: Float32Array.BYTES_PER_ELEMENT * 0,
stride: Float32Array.BYTES_PER_ELEMENT * 2,
divisor: 1
}),
nextPosition: (ctx, props) => ({
buffer: props.positionBuffer,
offset: Float32Array.BYTES_PER_ELEMENT * 2,
stride: Float32Array.BYTES_PER_ELEMENT * 2,
divisor: 1
}),
line: {
buffer: [[0, 1], [0, -1], [1, 1], [1, -1]],
divisor: 0
}
},
uniforms: {
aspect: ctx => ctx.viewportWidth / ctx.viewportHeight,
width: (ctx, props) => props.lineWidth / ctx.viewportHeight,
antialiasWidth: (ctx, props) => props.antialiasWidth,
alpha: regl.prop('lineOpacity'),
projectionView: regl.prop('projectionView')
},
depth: { enable: false },
blend: {
enable: true,
func: {
srcRGB: 1,
srcAlpha: 1,
dstRGB: 'one minus src alpha',
dstAlpha: 1
},
equation: {
rgb: 'add',
alpha: 'add'
}
},
primitive: 'triangle strip',
instances: (ctx, props) => props.count - 1,
count: 4
})
Insert cell
Insert cell
dimensions = [width, Math.floor(width * 0.5)]
Insert cell
import { Range } from '@observablehq/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