-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
25 changed files
with
635 additions
and
131 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> |
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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') | ||
}); | ||
}; |
Oops, something went wrong.