Skip to content

Instantly share code, notes, and snippets.

@dancingfrog
Forked from pbeshai/.block
Last active January 5, 2019 15:08
Show Gist options
  • Save dancingfrog/78f0fd6369a79082f19d27ee074fb905 to your computer and use it in GitHub Desktop.
Save dancingfrog/78f0fd6369a79082f19d27ee074fb905 to your computer and use it in GitHub Desktop.
Draw 100,000 points with regl
license: mit
height: 720
border: no
var regl=createREGL({onDone:function (err, regl) {console.log('Initialization of regl complete\n', regl);main(err, regl);}}); function main(t,n){var o=1e5,e=4,i=window.innerWidth,a=window.innerHeight,r=d3.randomNormal(0,.15),s=d3.range(o).map(function(t){return{x:r()*i+i/2,y:r()*a+a/2,color:[0,Math.random(),0]}}),l=n({frag:"\n\t\t// set the precision of floating point numbers\n\t precision highp float;\n\n\t // this value is populated by the vertex shader\n\t\tvarying vec3 fragColor;\n\n\t\tvoid main() {\n\t\t\t// gl_FragColor is a special variable that holds the color of a pixel\n\t\t\tgl_FragColor = vec4(fragColor, 1);\n\t\t}\n\t\t",vert:"\n\t\t// per vertex attributes\n\t\tattribute vec2 position;\n\t\tattribute vec3 color;\n\n\t\t// variables to send to the fragment shader\n\t\tvarying vec3 fragColor;\n\n\t\t// values that are the same for all vertices\n\t\tuniform float pointWidth;\n\t\tuniform float stageWidth;\n\t\tuniform float stageHeight;\n\n\t\t// helper function to transform from pixel space to normalized device coordinates (NDC)\n\t\t// in NDC (0,0) is the middle, (-1, -1) is the top left and (1, 1) is the bottom right.\n\t\tvec2 normalizeCoords(vec2 position) {\n\t\t\t// read in the positions into x and y vars\n float x = position[0];\n float y = position[1];\n\n\t\t\treturn vec2(\n\t 2.0 * ((x / stageWidth) - 0.5),\n\t // invert y since we think [0,0] is bottom left in pixel space\n\t -(2.0 * ((y / stageHeight) - 0.5)));\n\t\t}\n\n\t\tvoid main() {\n\t\t\t// update the size of a point based on the prop pointWidth\n\t\t\tgl_PointSize = pointWidth;\n\n // send color to the fragment shader\n fragColor = color;\n\n\t\t\t// scale to normalized device coordinates\n\t\t\t// gl_Position is a special variable that holds the position of a vertex\n gl_Position = vec4(normalizeCoords(position), 0.0, 1.0);\n\t\t}\n\t\t",attributes:{position:s.map(function(t){return[t.x,t.y]}),color:s.map(function(t){return t.color})},uniforms:{pointWidth:n.prop("pointWidth"),stageWidth:n.prop("stageWidth"),stageHeight:n.prop("stageHeight")},count:s.length,primitive:"points"});frameLoop=n.frame(function(){n.clear({color:[0,0,0,1],depth:1}),l({pointWidth:e,stageWidth:i,stageHeight:a}),frameLoop&&frameLoop.cancel()})}
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNjcmlwdC5qcyJdLCJuYW1lcyI6WyJtYWluIiwiZXJyIiwicmVnbCIsImNvbnN0IiwibnVtUG9pbnRzIiwicG9pbnRXaWR0aCIsIndpZHRoIiwid2luZG93IiwiaW5uZXJXaWR0aCIsImhlaWdodCIsImlubmVySGVpZ2h0Iiwicm5nIiwiZDMiLCJyYW5kb21Ob3JtYWwiLCJwb2ludHMiLCJyYW5nZSIsIm1hcCIsImkiLCJ4IiwieSIsImNvbG9yIiwiTWF0aCIsInJhbmRvbSIsImRyYXdQb2ludHMiLCJmcmFnIiwidmVydCIsImF0dHJpYnV0ZXMiLCJwb3NpdGlvbiIsImQiLCJ1bmlmb3JtcyIsInByb3AiLCJzdGFnZVdpZHRoIiwic3RhZ2VIZWlnaHQiLCJjb3VudCIsImxlbmd0aCIsInByaW1pdGl2ZSIsImZyYW1lTG9vcCIsImZyYW1lIiwiY2xlYXIiLCJkZXB0aCIsImNhbmNlbCIsIm9uRG9uZSJdLCJtYXBwaW5ncyI6IkFBQUEsUUFBU0EsTUFBS0MsRUFBS0MsR0FDbEJDLEdBQU1DLEdBQVksSUFDWkMsRUFBZSxFQUNmQyxFQUFRQyxPQUFPQyxXQUNmQyxFQUFTRixPQUFPRyxZQUdoQkMsRUFBUUMsR0FBQ0MsYUFBYyxFQUFFLEtBQ3pCQyxFQUFXRixHQUFDRyxNQUFNWCxHQUFXWSxJQUFJLFNBQUFDLEdBQUEsT0FDdENDLEVBQUlQLElBQVFMLEVBQVVBLEVBQVEsRUFDOUJhLEVBQUlSLElBQVFGLEVBQVdBLEVBQVMsRUFDaENXLE9BQVEsRUFBR0MsS0FBS0MsU0FBVSxNQUlyQkMsRUFBYXJCLEdBQ2xCc0IsS0FBTSxnVUFhTkMsS0FBTSw4dENBdUZQQyxZQUdEQyxTQUFLYixFQUFBRSxJQUFBLFNBQUFZLEdBQUEsT0FBQUEsRUFBQVYsRUFBQVUsRUFBQVQsS0EvQ0ZDLE1BQU9OLEVBQU9FLElBQUksU0FBQVksR0FBRSxNQUFHQSxHQUFFUixTQUcxQlMsVUFHQ3hCLFdBQVlILEVBQUs0QixLQUFLLGNBS3RCQyxXQUFZN0IsRUFBSzRCLEtBQUssY0FDdEJFLFlBQWE5QixFQUFLNEIsS0FBSyxnQkFJeEJHLE1BQU9uQixFQUFPb0IsT0FHZEMsVUFBVyxVQUlaQyxXQUFZbEMsRUFBS21DLE1BQU0sV0FFdEJuQyxFQUFLb0MsT0FFSmxCLE9BQVEsRUFBRyxFQUFHLEVBQUcsR0FDakJtQixNQUFPLElBS1JoQixHQUNDbEIsV0FBQUEsRUFDQTBCLFdBQVl6QixFQUNaMEIsWUFBYXZCLElBSVYyQixXQUNIQSxVQUFVSSxXQU1idEMsTUFFRXVDLE9BQVF6QyIsImZpbGUiOiJzY3JpcHQuanMiLCJzb3VyY2VzQ29udGVudCI6WyJmdW5jdGlvbiBtYWluKGVyciwgcmVnbCkge1xuXHRjb25zdCBudW1Qb2ludHMgPSAxMDAwMDA7XG5cdGNvbnN0IHBvaW50V2lkdGggPSA0O1xuXHRjb25zdCB3aWR0aCA9IHdpbmRvdy5pbm5lcldpZHRoO1xuXHRjb25zdCBoZWlnaHQgPSB3aW5kb3cuaW5uZXJIZWlnaHQ7XG5cblx0Ly8gY3JlYXRlIGluaXRpYWwgc2V0IG9mIHBvaW50c1xuXHRjb25zdCBybmcgPSBkMy5yYW5kb21Ob3JtYWwoMCwgMC4xNSk7XG5cdGNvbnN0IHBvaW50cyA9IGQzLnJhbmdlKG51bVBvaW50cykubWFwKGkgPT4gKHtcblx0XHR4OiAocm5nKCkgKiB3aWR0aCkgKyAod2lkdGggLyAyKSxcblx0XHR5OiAocm5nKCkgKiBoZWlnaHQpICsgKGhlaWdodCAvIDIpLFxuXHRcdGNvbG9yOiBbMCwgTWF0aC5yYW5kb20oKSwgMF0sXG5cdH0pKTtcblxuXHQvLyBmdW5jdGlvbiB0byBjb21waWxlIGEgZHJhdyBwb2ludHMgcmVnbCBmdW5jXG5cdGNvbnN0IGRyYXdQb2ludHMgPSByZWdsKHtcblx0XHRmcmFnOiBgXG5cdFx0Ly8gc2V0IHRoZSBwcmVjaXNpb24gb2YgZmxvYXRpbmcgcG9pbnQgbnVtYmVyc1xuXHQgIHByZWNpc2lvbiBoaWdocCBmbG9hdDtcblxuXHQgIC8vIHRoaXMgdmFsdWUgaXMgcG9wdWxhdGVkIGJ5IHRoZSB2ZXJ0ZXggc2hhZGVyXG5cdFx0dmFyeWluZyB2ZWMzIGZyYWdDb2xvcjtcblxuXHRcdHZvaWQgbWFpbigpIHtcblx0XHRcdC8vIGdsX0ZyYWdDb2xvciBpcyBhIHNwZWNpYWwgdmFyaWFibGUgdGhhdCBob2xkcyB0aGUgY29sb3Igb2YgYSBwaXhlbFxuXHRcdFx0Z2xfRnJhZ0NvbG9yID0gdmVjNChmcmFnQ29sb3IsIDEpO1xuXHRcdH1cblx0XHRgLFxuXG5cdFx0dmVydDogYFxuXHRcdC8vIHBlciB2ZXJ0ZXggYXR0cmlidXRlc1xuXHRcdGF0dHJpYnV0ZSB2ZWMyIHBvc2l0aW9uO1xuXHRcdGF0dHJpYnV0ZSB2ZWMzIGNvbG9yO1xuXG5cdFx0Ly8gdmFyaWFibGVzIHRvIHNlbmQgdG8gdGhlIGZyYWdtZW50IHNoYWRlclxuXHRcdHZhcnlpbmcgdmVjMyBmcmFnQ29sb3I7XG5cblx0XHQvLyB2YWx1ZXMgdGhhdCBhcmUgdGhlIHNhbWUgZm9yIGFsbCB2ZXJ0aWNlc1xuXHRcdHVuaWZvcm0gZmxvYXQgcG9pbnRXaWR0aDtcblx0XHR1bmlmb3JtIGZsb2F0IHN0YWdlV2lkdGg7XG5cdFx0dW5pZm9ybSBmbG9hdCBzdGFnZUhlaWdodDtcblxuXHRcdC8vIGhlbHBlciBmdW5jdGlvbiB0byB0cmFuc2Zvcm0gZnJvbSBwaXhlbCBzcGFjZSB0byBub3JtYWxpemVkIGRldmljZSBjb29yZGluYXRlcyAoTkRDKVxuXHRcdC8vIGluIE5EQyAoMCwwKSBpcyB0aGUgbWlkZGxlLCAoLTEsIC0xKSBpcyB0aGUgdG9wIGxlZnQgYW5kICgxLCAxKSBpcyB0aGUgYm90dG9tIHJpZ2h0LlxuXHRcdHZlYzIgbm9ybWFsaXplQ29vcmRzKHZlYzIgcG9zaXRpb24pIHtcblx0XHRcdC8vIHJlYWQgaW4gdGhlIHBvc2l0aW9ucyBpbnRvIHggYW5kIHkgdmFyc1xuICAgICAgZmxvYXQgeCA9IHBvc2l0aW9uWzBdO1xuICAgICAgZmxvYXQgeSA9IHBvc2l0aW9uWzFdO1xuXG5cdFx0XHRyZXR1cm4gdmVjMihcblx0ICAgICAgMi4wICogKCh4IC8gc3RhZ2VXaWR0aCkgLSAwLjUpLFxuXHQgICAgICAvLyBpbnZlcnQgeSBzaW5jZSB3ZSB0aGluayBbMCwwXSBpcyBib3R0b20gbGVmdCBpbiBwaXhlbCBzcGFjZVxuXHQgICAgICAtKDIuMCAqICgoeSAvIHN0YWdlSGVpZ2h0KSAtIDAuNSkpKTtcblx0XHR9XG5cblx0XHR2b2lkIG1haW4oKSB7XG5cdFx0XHQvLyB1cGRhdGUgdGhlIHNpemUgb2YgYSBwb2ludCBiYXNlZCBvbiB0aGUgcHJvcCBwb2ludFdpZHRoXG5cdFx0XHRnbF9Qb2ludFNpemUgPSBwb2ludFdpZHRoO1xuXG4gICAgICAvLyBzZW5kIGNvbG9yIHRvIHRoZSBmcmFnbWVudCBzaGFkZXJcbiAgICAgIGZyYWdDb2xvciA9IGNvbG9yO1xuXG5cdFx0XHQvLyBzY2FsZSB0byBub3JtYWxpemVkIGRldmljZSBjb29yZGluYXRlc1xuXHRcdFx0Ly8gZ2xfUG9zaXRpb24gaXMgYSBzcGVjaWFsIHZhcmlhYmxlIHRoYXQgaG9sZHMgdGhlIHBvc2l0aW9uIG9mIGEgdmVydGV4XG4gICAgICBnbF9Qb3NpdGlvbiA9IHZlYzQobm9ybWFsaXplQ29vcmRzKHBvc2l0aW9uKSwgMC4wLCAxLjApO1xuXHRcdH1cblx0XHRgLFxuXG5cdFx0YXR0cmlidXRlczoge1xuXHRcdFx0Ly8gZWFjaCBvZiB0aGVzZSBnZXRzIG1hcHBlZCB0byBhIHNpbmdsZSBlbnRyeSBmb3IgZWFjaCBvZiB0aGUgcG9pbnRzLlxuXHRcdFx0Ly8gdGhpcyBtZWFucyB0aGUgdmVydGV4IHNoYWRlciB3aWxsIHJlY2VpdmUganVzdCB0aGUgcmVsZXZhbnQgdmFsdWUgZm9yIGEgZ2l2ZW4gcG9pbnQuXG5cdFx0XHRwb3NpdGlvbjogcG9pbnRzLm1hcChkID0+IFtkLngsIGQueV0pLFxuXHRcdFx0Y29sb3I6IHBvaW50cy5tYXAoZCA9PiBkLmNvbG9yKSxcblx0XHR9LFxuXG5cdFx0dW5pZm9ybXM6IHtcblx0XHRcdC8vIGJ5IHVzaW5nIGByZWdsLnByb3BgIHRvIHBhc3MgdGhlc2UgaW4sIHdlIGNhbiBzcGVjaWZ5IHRoZW0gYXMgYXJndW1lbnRzXG5cdFx0XHQvLyB0byBvdXIgZHJhd1BvaW50cyBmdW5jdGlvblxuXHRcdFx0cG9pbnRXaWR0aDogcmVnbC5wcm9wKCdwb2ludFdpZHRoJyksXG5cblx0XHRcdC8vIHJlZ2wgYWN0dWFsbHkgcHJvdmlkZXMgdGhlc2UgYXMgdmlld3BvcnRXaWR0aCBhbmQgdmlld3BvcnRIZWlnaHQgYnV0IElcblx0XHRcdC8vIGFtIHVzaW5nIHRoZXNlIG91dHNpZGUgYW5kIEkgd2FudCB0byBlbnN1cmUgdGhleSBhcmUgdGhlIHNhbWUgbnVtYmVycyxcblx0XHRcdC8vIHNvIEkgYW0gZXhwbGljaXRseSBwYXNzaW5nIHRoZW0gaW4uXG5cdFx0XHRzdGFnZVdpZHRoOiByZWdsLnByb3AoJ3N0YWdlV2lkdGgnKSxcblx0XHRcdHN0YWdlSGVpZ2h0OiByZWdsLnByb3AoJ3N0YWdlSGVpZ2h0JyksXG5cdFx0fSxcblxuXHRcdC8vIHNwZWNpZnkgdGhlIG51bWJlciBvZiBwb2ludHMgdG8gZHJhd1xuXHRcdGNvdW50OiBwb2ludHMubGVuZ3RoLFxuXG5cdFx0Ly8gc3BlY2lmeSB0aGF0IGVhY2ggdmVydGV4IGlzIGEgcG9pbnQgKG5vdCBwYXJ0IG9mIGEgbWVzaClcblx0XHRwcmltaXRpdmU6ICdwb2ludHMnLFxuXHR9KTtcblxuXHQvLyBzdGFydCBhbiBhbmltYXRpb24gbG9vcFxuXHRmcmFtZUxvb3AgPSByZWdsLmZyYW1lKCgpID0+IHtcblx0XHQvLyBjbGVhciB0aGUgYnVmZmVyXG5cdFx0cmVnbC5jbGVhcih7XG5cdFx0XHQvLyBiYWNrZ3JvdW5kIGNvbG9yIChibGFjaylcblx0XHRcdGNvbG9yOiBbMCwgMCwgMCwgMV0sXG5cdFx0XHRkZXB0aDogMSxcblx0XHR9KTtcblxuXHRcdC8vIGRyYXcgdGhlIHBvaW50cyB1c2luZyBvdXIgY3JlYXRlZCByZWdsIGZ1bmNcblx0XHQvLyBub3RlIHRoYXQgdGhlIGFyZ3VtZW50cyBhcmUgYXZhaWxhYmxlIHZpYSBgcmVnbC5wcm9wYC5cblx0XHRkcmF3UG9pbnRzKHtcblx0XHRcdHBvaW50V2lkdGgsXG5cdFx0XHRzdGFnZVdpZHRoOiB3aWR0aCxcblx0XHRcdHN0YWdlSGVpZ2h0OiBoZWlnaHQsXG5cdFx0fSk7XG5cblx0XHQvLyBzaW5jZSB3ZSBhcmUgb25seSBkcmF3aW5nIG9uY2UgcmlnaHQgbm93LCBsZXQncyBqdXN0IGNhbmNlbCB0aGUgbG9vcCBpbW1lZGlhdGVseVxuXHRcdGlmIChmcmFtZUxvb3ApIHtcblx0XHRcdGZyYW1lTG9vcC5jYW5jZWwoKTtcblx0XHR9XG5cdH0pO1xufVxuXG4vLyBpbml0aWFsaXplIHJlZ2xcbnJlZ2woe1xuICAvLyBjYWxsYmFjayB3aGVuIHJlZ2wgaXMgaW5pdGlhbGl6ZWRcbiAgb25Eb25lOiBtYWluXG59KTtcbiJdfQ==
<!DOCTYPE html>
<title>Draw 100,000 points with regl</title>
<body>
<script src="https://npmcdn.com/regl/dist/regl.min.js"></script>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="dist.js"></script>
</body>
const regl = createREGL({onDone:function (err, regl) {console.log('Initialization of regl complete\n', regl);main(err, regl);}});
function main(err, regl) {
const numPoints = 100000;
const pointWidth = 4;
const width = window.innerWidth;
const height = window.innerHeight;
// create initial set of points
const rng = d3.randomNormal(0, 0.15);
const points = d3.range(numPoints).map(i => ({
x: (rng() * width) + (width / 2),
y: (rng() * height) + (height / 2),
color: [0, Math.random(), 0],
}));
// function to compile a draw points regl func
const drawPoints = regl({
frag: `
// set the precision of floating point numbers
precision highp float;
// this value is populated by the vertex shader
varying vec3 fragColor;
void main() {
// gl_FragColor is a special variable that holds the color of a pixel
gl_FragColor = vec4(fragColor, 1);
}
`,
vert: `
// per vertex attributes
attribute vec2 position;
attribute vec3 color;
// variables to send to the fragment shader
varying vec3 fragColor;
// values that are the same for all vertices
uniform float pointWidth;
uniform float stageWidth;
uniform float stageHeight;
// helper function to transform from pixel space to normalized device coordinates (NDC)
// in NDC (0,0) is the middle, (-1, 1) is the top left and (1, -1) is the bottom right.
vec2 normalizeCoords(vec2 position) {
// read in the positions into x and y vars
float x = position[0];
float y = position[1];
return vec2(
2.0 * ((x / stageWidth) - 0.5),
// invert y since we think [0,0] is bottom left in pixel space
-(2.0 * ((y / stageHeight) - 0.5)));
}
void main() {
// update the size of a point based on the prop pointWidth
gl_PointSize = pointWidth;
// send color to the fragment shader
fragColor = color;
// scale to normalized device coordinates
// gl_Position is a special variable that holds the position of a vertex
gl_Position = vec4(normalizeCoords(position), 0.0, 1.0);
}
`,
attributes: {
// each of these gets mapped to a single entry for each of the points.
// this means the vertex shader will receive just the relevant value for a given point.
position: points.map(d => [d.x, d.y]),
color: points.map(d => d.color),
},
uniforms: {
// by using `regl.prop` to pass these in, we can specify them as arguments
// to our drawPoints function
pointWidth: regl.prop('pointWidth'),
// regl actually provides these as viewportWidth and viewportHeight but I
// am using these outside and I want to ensure they are the same numbers,
// so I am explicitly passing them in.
stageWidth: regl.prop('stageWidth'),
stageHeight: regl.prop('stageHeight'),
},
// specify the number of points to draw
count: points.length,
// specify that each vertex is a point (not part of a mesh)
primitive: 'points',
});
// start an animation loop
frameLoop = regl.frame(() => {
// clear the buffer
regl.clear({
// background color (black)
color: [0, 0, 0, 1],
depth: 1,
});
// draw the points using our created regl func
// note that the arguments are available via `regl.prop`.
drawPoints({
pointWidth,
stageWidth: width,
stageHeight: height,
});
// since we are only drawing once right now, let's just cancel the loop immediately
if (frameLoop) {
frameLoop.cancel();
}
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment