Code
const regl = createREGL({extensions: ['ANGLE_instanced_arrays']});
const drawLines = reglLines(regl, {
vert: `
precision highp float;
#pragma lines: attribute vec2 xy;
#pragma lines: position = getPosition(xy);
#pragma lines: width = getWidth();
#pragma lines: varying vec2 pos = getXY(xy);
vec4 getPosition(vec2 xy) {
return vec4(xy, 0, 1);
}
float getWidth() { return 40.0; }
vec2 getXY(vec2 xy) { return xy; }`,
frag: `
precision lowp float;
varying vec2 pos;
void main () {
// Convert the x-coordinate into a color
gl_FragColor = vec4(0.6 + 0.4 * cos(8.0 * (pos.x - vec3(0, 1, 2) * 3.141 / 3.0)), 0.7);
}`,
// Turn off depth and turn on blending to make it very clear if we accidentally
// draw end caps twice
depth: { enable: false },
cull: {enable: true, face: 'back'},
blend: {
enable: true,
func: { srcRGB: "src alpha", srcAlpha: 1, dstRGB: "one minus src alpha", dstAlpha: 1 }
},
});
const n = 31;
const lineCount = 10;
function xy (line, i) {
let t = (i / (n - 1) * 2 - 1) * 0.9;
const y = ((line + 0.5) / lineCount * 2 - 1) * 0.9;
return [t, y + 1 / lineCount * Math.sin((t - line * 0.1) * 8.0)];
}
// Start with a break in order to signal a cap
const positions = [[NaN, NaN]];
for (let line = 0; line < lineCount; line++) {
for (let i = 0; i < n; i++) {
positions.push(xy(line, i));
}
// Signal a cap after each line
positions.push([NaN, NaN]);
}
// After this, render as normal!
const lineData = {
// Trigger the command to automatically insert caps at any break, signaled by a position with (w = 0)
insertCaps: true,
join: 'round',
cap: 'round',
vertexCount: positions.length,
vertexAttributes: {
xy: regl.buffer(positions),
},
};
function draw () {
regl.poll();
regl.clear({color: [0.2, 0.2, 0.2, 1]});
drawLines(lineData);
}
draw();
window.addEventListener('resize', draw);