Code
const regl = createREGL({
extensions: ['ANGLE_instanced_arrays'],
optionalExtensions: ['OES_vertex_array_object']
});
if (!regl.hasExtension('OES_vertex_array_object')) {
console.warn('Unable to load OES_vertex_array_object extension. VAOs will be emulated.');
}
// This command illustrates usage of Vertex Array Objects (VAOs). The general idea of VAOs is that
// you define the full state of strides and offsets up front to avoid having to configure it over
// and over.
//
// In the context of regl-gpu-lines, it means that you move vertexAttributes and endpointAttributes
// to a separate call to `drawLines.vao()`, then simply pass the resulting object when drawing lines
// instead of vertexAttributes and endpointAttributes.
const drawLines = reglLines(regl, {
vert: `
precision highp float;
// Use a vec2 attribute to construt the vec4 vertex position
#pragma lines: attribute vec2 xy;
#pragma lines: position = getPosition(xy);
vec4 getPosition(vec2 xy) {
return vec4(xy, 0, 1);
}
#pragma lines: attribute float orientation;
#pragma lines: orientation = getOrientation(orientation)
float getOrientation(float o) { return o; }
// Return the line width from a uniorm
#pragma lines: width = getWidth();
uniform float width;
float getWidth() {
return width;
}`,
frag: `
precision lowp float;
void main () {
gl_FragColor = vec4(1);
}`,
// Multiply the width by the pixel ratio for consistent width
uniforms: {
width: (ctx, props) => ctx.pixelRatio * props.width
},
});
// Construct an array of xy pairs
const n = 11;
const xy = [...Array(n).keys()]
.map(i => (i / (n - 1) * 2.0 - 1.0) * 0.8)
.map(t => [t, 0.5 * Math.sin(8.0 * t)]);
// Instead of passing vertex and endpoint attributes with line data, we instead allocate a Vertex
// Array Object (VAO) up front, then pass the resulting object to the draw command. This prevents
// having to compute and configure strides and offsets on every frame.
const vao = drawLines.vao({
vertexAttributes: {
xy: regl.buffer(xy)
},
endpointAttributes: {
// Note the use of flat() which is required for regl to correctly infer the dimensionality of
// the data, which must be correctly passed to the VAO.
orientation: regl.buffer([Array(3).fill(reglLines.CAP_START), Array(3).fill(reglLines.CAP_END)].flat()),
xy: regl.buffer([xy.slice(0, 3), xy.slice(-3).reverse()].flat())
}
});
function draw () {
// After the above step, line proceeds as normal, except instead of attributes, we pass it the
// preallocated VAO object.
const lineData = {
width: 30,
join: 'round',
cap: 'round',
vertexCount: xy.length,
endpointCount: 2,
vao
};
regl.poll();
regl.clear({color: [0.2, 0.2, 0.2, 1]});
drawLines(lineData);
}
draw();
window.addEventListener('resize', draw);