Skip to content

Commit

Permalink
🔎
Browse files Browse the repository at this point in the history
  • Loading branch information
rreusser committed Aug 19, 2023
1 parent f5ff437 commit 7eea970
Show file tree
Hide file tree
Showing 25 changed files with 635 additions and 131 deletions.
256 changes: 128 additions & 128 deletions nav.bundle.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions quasiinfinite-zoom/bundle.js

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions quasiinfinite-zoom/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE html><html lang="en" dir="ltr"><head><title>Quasiinfinite zoom</title><meta charset="utf-8"><meta name="application-name" content="Quasiinfinite zoom">
<meta name="subject" content="Repeated quasirandom points to create the illusion of infinite zoom">
<meta name="abstract" content="Repeated quasirandom points to create the illusion of infinite zoom">
<meta name="twitter:title" content="Quasiinfinite zoom">
<meta name="description" content="Repeated quasirandom points to create the illusion of infinite zoom">
<meta name="twitter:description" content="Repeated quasirandom points to create the illusion of infinite zoom">
<meta name="author" content="Ricky Reusser">
<meta name="twitter:creator" content="Ricky Reusser">
<meta name="twitter:card" content="summary">
<meta property="og:title" content="Quasiinfinite zoom">
<meta property="og:description" content="Repeated quasirandom points to create the illusion of infinite zoom">
<meta property="article:author" content="Ricky Reusser">
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport" /></head><body><script src="bundle.js"></script><script src="../nav.bundle.js"></script></body></html>
2 changes: 1 addition & 1 deletion sketches/index.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion sketches/index.js

Large diffs are not rendered by default.

Binary file modified sketches/static/cubic-roots-thumbnail.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed sketches/static/cubic-roots-thumbnail.png
Binary file not shown.
Binary file modified sketches/static/mandelbrot-thumbnail.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sketches/static/quasiinfinite-zoom-thumbnail.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed src/src/cubic-roots/thumbnail.png
Binary file not shown.
56 changes: 56 additions & 0 deletions src/src/quasiinfinite-zoom/configure-linear-scales.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
'use strict';

const mat3create = require('gl-mat3/create');
const mat3invert = require('gl-mat3/invert');
const mat4create = require('gl-mat4/create');
const mat3fromLinearScales = require('./mat3-from-linear-scales.js');
const mat4fromMat3 = require('./mat4-from-mat3.js');

module.exports = function createReglLinearScaleConfiguration(regl) {
const matrices = {
view3: mat3create(),
inverseView3: mat3create(),
view: mat4create(),
inverseView: mat4create(),
xDomain: [0, 0],
yDomain: [0, 0],
dirty: true,
};
const command = regl({
context: {
view3: regl.prop("view3"),
inverseView3: regl.prop("inverseView3"),
view: regl.prop("view"),
inverseView: regl.prop("inverseView"),
xDomain: regl.prop('xDomain'),
yDomain: regl.prop('yDomain'),
dirty: regl.prop('dirty'),
},
uniforms: {
view3: regl.prop("view3"),
inverseView3: regl.prop("inverseView3"),
view: regl.prop("view"),
inverseView: regl.prop("inverseView"),
xDomain: regl.prop('xDomain'),
yDomain: regl.prop('yDomain'),
}
});

return function (scales, clbk) {
mat3fromLinearScales(matrices.view3, scales);
mat3invert(matrices.inverseView3, matrices.view3);
mat4fromMat3(matrices.view, matrices.view3);
mat4fromMat3(matrices.inverseView, matrices.inverseView3);
const xd = scales.x.domain();
const xc = 0.5 * (xd[1] + xd[0]);
const xr = 0.5 * (xd[1] - xd[0]);
const yd = scales.y.domain();
const yc = 0.5 * (yd[1] + yd[0]);
const yr = 0.5 * (yd[1] - yd[0]);
matrices.xDomain = [xc - xr, xc + xr];
matrices.yDomain = [yc - yr, yc + yr];
matrices.dirty = scales.dirty;
command(matrices, clbk);
scales.dirty = false;
};
}
9 changes: 9 additions & 0 deletions src/src/quasiinfinite-zoom/configure-uniforms.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
'use strict';

module.exports = function (regl) {
return regl({
uniforms: {
globalScale: (_, {debug}) => Math.pow(2, -debug)
}
});
}
41 changes: 41 additions & 0 deletions src/src/quasiinfinite-zoom/configure-viewport.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
const mat3create = require('gl-mat3/create');

const DEFAULT_MARGIN = { t: 0, r: 0, b: 0, l: 0 };

module.exports = function createReglViewportConfiguration(regl) {
const viewport3 = mat3create();

let command = regl({
viewport: {
x: (ctx, props) => ctx.pixelRatio * props.margin.l,
y: (ctx, props) => ctx.pixelRatio * props.margin.b,
width: (ctx, props) => ctx.viewportWidth - ctx.pixelRatio * (props.margin.r + props.margin.l),
height: (ctx, props) => ctx.viewportHeight - ctx.pixelRatio * (props.margin.t + props.margin.b)
},
uniforms: {
viewportResolution: (ctx, props) => [
ctx.viewportWidth,
ctx.viewportHeight
],
framebufferResolution: (ctx) => [
ctx.framebufferWidth,
ctx.framebufferHeight
],
inverseViewportResolution: (ctx, props) => [
1 / ctx.viewportWidth,
1 / ctx.viewportHeight
],
inverseFramebufferResolution: (ctx) => [
1 / ctx.framebufferWidth,
1 / ctx.framebufferHeight
],
pixelRatio: regl.context("pixelRatio")
}
});

return function (viewport, callback) {
const margin = Object.assign({}, DEFAULT_MARGIN);
if (viewport && viewport.margin) Object.assign(margin, viewport.margin);
command({ margin }, callback);
};
};
45 changes: 45 additions & 0 deletions src/src/quasiinfinite-zoom/create-zoom.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
const d3 = require('d3');

function createZoom(scales, onZoom) {
const xOriginal = scales.x.copy();
const yOriginal = scales.y.copy();

return d3.zoom()
.scaleExtent([1e-5, 1e5])
.on("zoom", function () {
const t = d3.event.transform;
let range = scales.x.range().map(t.invertX, t);
scales.x.domain(xOriginal.domain());
scales.x.domain(range.map(scales.x.invert, scales.x));

range = scales.y.range().map(t.invertY, t);
scales.y.domain(yOriginal.domain());
scales.y.domain(range.map(scales.y.invert, scales.y));
scales.dirty = true;

onZoom && onZoom();
});
}

module.exports = function attachPanZoom(el, scales, onZoom) {
const xRange = scales.x.range();
const yRange = scales.y.range();
const aspect = (xRange[1] - xRange[0]) / (yRange[0] - yRange[1]);

const xDom = scales.x.domain();
const yDom = scales.y.domain();
const yRng = 0.5 * (yDom[1] - yDom[0]);
const xCen = 0.5 * (xDom[1] + xDom[0]);
const xMin = xCen - yRng * aspect;
const xMax = xCen + yRng * aspect;
const yMin = yDom[0];
const yMax = yDom[1];

scales.x.domain([xMin, xMax]).range(xRange);
scales.y.domain([yMin, yMax]).range(yRange);

el.__zoom = null;
d3.select(el).call(createZoom(scales, onZoom));

onZoom && onZoom();
}
23 changes: 23 additions & 0 deletions src/src/quasiinfinite-zoom/draw-box.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
'use strict';

module.exports = function (regl) {
return regl({
vert: `
precision highp float;
attribute vec2 xy;
uniform float globalScale;
void main () {
gl_Position = vec4(xy * globalScale, 0, 1);
}`,
frag: `
precision lowp float;
void main () {
gl_FragColor = vec4(1, 0, 0, 1);
}`,
attributes: {
xy: [-1, -1, 1, -1, 1, 1, -1, 1, -1, -1]
},
primitive: 'line strip',
count: 5
});
}
106 changes: 106 additions & 0 deletions src/src/quasiinfinite-zoom/draw-points.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
const mat4create = require('gl-mat4/create');

function mod(n, m) {
return ((n % m) + m) % m;
}

module.exports = function (regl) {
return regl({
vert: `
precision highp float;
attribute vec3 uv;
uniform sampler2D colorscale;
uniform float pixelRatio, pointSize, z, aspect, zblend, zrange, globalScale, scalePoints, fadeOutStart, fadeInEnd;
uniform vec2 xDomain, yDomain;
uniform vec4 domain;
uniform mat4 inverseView, view;
varying float opacity, vPointSize;
varying vec4 color;
float linearstep (float a, float b, float x) {
return clamp((x - a) / (b - a), 0.0, 1.0);
}
void main () {
float scale = pow(2.0, z + uv.z * zblend);
vec2 cen = (domain.zw + domain.xy) * 0.5;
vec2 rng = (domain.zw - domain.xy) * vec2(1, aspect) * (0.5 * scale);
vec2 base = pow(vec2(2.0), ceil(log2(2.0 * rng)));
vec2 offset = base * floor(0.5 * domain.xy / base) * 2.0;
vec2 offset2 = base * floor(domain.xy / base);
vec2 shift = mod(offset2 / base, 2.0);
vec2 xy = uv.xy;
xy += shift * vec2(lessThan(xy, vec2(0.5)));
xy = xy * (2.0 * base) + offset;
gl_Position = view * vec4(xy, 0, 1);
float zfrac = 1.0 - fract(log2(2.0 * rng.x)) + z;
float sc = zrange / 3.0;
opacity = smoothstep(0.0, 0.01 + 3.0 * fadeInEnd * sc, zfrac) * smoothstep(3.0 * sc, 2.999 * fadeOutStart * sc, zfrac);
gl_PointSize = pixelRatio * pointSize * pow(2.0, (zfrac - zrange * 0.5) * scalePoints);
vPointSize = gl_PointSize;
color = texture2D(colorscale, vec2(uv.z, 0.5));
gl_Position.xy *= globalScale;
}`,
frag: `
precision highp float;
varying float opacity, vPointSize;
uniform float pixelRatio, pointSize;
varying vec4 color;
float linearstep (float a, float b, float x) {
return clamp((x - a) / (b - a), 0.0, 1.0);
}
void main () {
float r = length(gl_PointCoord.xy - 0.5) * 2.0 * vPointSize;
float alpha = linearstep(vPointSize, vPointSize - 1.0, r);
if (alpha == 0.0) discard;
gl_FragColor = color;
gl_FragColor.a *= opacity * alpha;
}`,
attributes: {
uv: regl.prop('xy')
},
uniforms: {
pixelRatio: regl.context('pixelRatio'),
pointSize: regl.prop('pointSize'),
offset: regl.prop('offset'),
base: regl.prop('base'),
shift: regl.prop('shift'),
aspect: ({viewportWidth, viewportHeight}) => viewportWidth / viewportHeight,
z: regl.prop('z'),
xDomain: regl.prop('xDomain'),
yDomain: regl.prop('yDomain'),
domain: (_, {xDomain, yDomain}) => [xDomain[0], yDomain[0], xDomain[1], yDomain[1]],
zrange: regl.prop('zrange'),
zblend: regl.prop('zblend'),
colorscale: regl.prop('colorscale'),
fadeOutStart: regl.prop('fadeOutStart'),
fadeInEnd: regl.prop('fadeInEnd'),
scalePoints: (_, {scalePoints}) => scalePoints ? 1 : 0
},
blend: {
enable: true,
func: {
srcRGB: 'src alpha',
srcAlpha: 1,
dstRGB: 1,
dstAlpha: 1
},
equation: {
rgb: 'add',
alpha: 'add'
},
},
depth: {
enable: false
},
primitive: 'points',
count: regl.prop('count')
});
};
Loading

0 comments on commit 7eea970

Please sign in to comment.