try { window.regltick.cancel() } catch(e){} console.clear() var sel = d3.select('#graph').html('') var c = d3.conventions({sel, layers: 'ds', margin: {left: 30, bottom: 30}, totalHeight: innerHeight}) c.x.domain([0, 1]).range([-1, 1]) c.y.domain([0, 1]).range([-1, 1]) var data = d3.range(100000).map(d => { var y = Math.random() var x = Math.random() var uniform = [ c.x(x), c.y(y), 1 ] var left = [ c.x(y*x), c.y(y), 1 ] return {d, y, uniform, left} }) c.x.range([0, c.width]) c.y.range([c.height, 0]) d3.drawAxis(c) reglLib({onDone, container: c.layers[0].node()}) function onDone(err, regl){ if (err) return console.log(err) window.regl = regl var count = data.length var curIndex = 0 datasets = ['uniform', 'left'].map(str => { var pos = data.map(d => d[str]) return {str, pos} }) const fbo_texture = regl.texture({width: 2*960, height: 2*500, min: 'linear', mag: 'linear'}) // to match the size of the canvas const fbo = regl.framebuffer({color: [fbo_texture]}) var drawPoints = regl({ vert: ` precision mediump float; attribute vec3 xyz0, xyz1; varying float c; uniform float interp, radius; void main() { vec3 pos = mix(xyz0, xyz1, interp); gl_Position = vec4(pos.xy, 0, 1); gl_PointSize = radius; }`, frag: ` precision mediump float; varying float c; void main() { vec4 color = vec4(1.0, 0.0, 1.0, 0.1); gl_FragColor = vec4(color.rgb * color.a, color.a); }`, attributes: { xyz0: () => datasets[curIndex % datasets.length].pos, xyz1: () => datasets[(curIndex + 1) % datasets.length].pos }, uniforms: { radius: () => 8, interp: (ctx, props) => Math.max(0, Math.min(1, props.interp)) }, primitive: 'point', count: count, framebuffer: fbo, depth: { enable: false }, blend: { enable: true, func: { srcRGB: 'one', srcAlpha: 1, dstRGB: 'one minus src alpha', dstAlpha: 1 }, equation: { rgb: 'add', alpha: 'add' }, color: [0, 0, 0, 0] // only needed for 'constant' blend color }, }) const demultiply = regl({ frag: ` precision mediump float; uniform sampler2D u_texture; varying vec2 v_uv; void main() { vec4 premultiplied_color = texture2D(u_texture, v_uv); gl_FragColor = premultiplied_color / premultiplied_color.a; }`, vert: ` precision highp float; attribute vec2 a_uv; varying vec2 v_uv; void main() { v_uv = a_uv; gl_Position = vec4(2.0 * v_uv - 1.0, 0.0, 1.0); }`, uniforms: { u_texture: fbo_texture, }, depth: { enable: false, }, count: 3, attributes: { a_uv: [-2, 0, 0, -2, 2, 2] }, }) var lastSwitchTime = 0 var switchInterval = 5 var switchDuration = 5 window.regltick = regl.frame(({time}) => { if ((time - lastSwitchTime) > switchInterval) { lastSwitchTime = time curIndex = (curIndex + 1) % datasets.length } fbo.use(() => { regl.clear({color: [1, 1, 1, 0]}) }) drawPoints({interp: d3.easeBackOut((time - lastSwitchTime) / switchDuration)}) demultiply() }) }