diff --git a/deploy/site/ambient.js b/deploy/site/ambient.js
index eb49625..e4f6613 100644
--- a/deploy/site/ambient.js
+++ b/deploy/site/ambient.js
@@ -78,7 +78,15 @@
for (let i = 0; i < message.length; i++) seed = Math.imul(seed ^ message.charCodeAt(i), 16777619);
return seed >>> 0;
}
- if (typeof module !== 'undefined') module.exports = { createCurrent, position, receive, absorb, resizeCurrent };
+ function grainFrom(seed) {
+ const random = randomFrom(seed);
+ return Array.from({ length: 4200 }, () => {
+ const x = random() * 384, y = random() * 384;
+ const direction = Math.sin(x / 47) * .4 + Math.cos(y / 61) * .3;
+ return { x, y, length: .6 + random() ** 3 * 2.8, direction, alpha: .12 + random() ** 2 * .25 };
+ });
+ }
+ if (typeof module !== 'undefined') module.exports = { createCurrent, position, receive, absorb, resizeCurrent, grainFrom };
if (typeof document === 'undefined') return;
const canvas = document.querySelector('canvas[data-current]');
if (!canvas) return;
@@ -88,6 +96,26 @@
const reduced = matchMedia('(prefers-reduced-motion: reduce)');
let width = 0, height = 0, frame = 0, last = 0, entropy = 0;
let socket, retry;
+ let grain, grainSeed;
+ function texture() {
+ if (grain && grainSeed === current.seed) return grain;
+ const tile = document.createElement('canvas');
+ tile.width = tile.height = 768;
+ const surface = tile.getContext('2d');
+ surface.scale(2, 2);
+ for (const fleck of grainFrom(current.seed)) {
+ surface.strokeStyle = `rgba(145,168,161,${fleck.alpha})`;
+ surface.lineWidth = .65;
+ surface.beginPath();
+ surface.moveTo(fleck.x, fleck.y);
+ surface.lineTo(fleck.x + fleck.length, fleck.y + fleck.direction * fleck.length);
+ surface.stroke();
+ }
+ grain = context.createPattern(tile, 'repeat');
+ grain.setTransform(new DOMMatrix().scale(.5));
+ grainSeed = current.seed;
+ return grain;
+ }
function connect() {
clearTimeout(retry);
if (document.hidden || socket) return;
@@ -101,6 +129,7 @@
function paint(now) {
const phase = reduced.matches ? current.to : position(current, now);
const t = reduced.matches ? 1 : progress(current, now);
+ const surface = texture();
context.clearRect(0, 0, width, height);
for (const shard of current.shards) {
const points = shard.points.map(([x, y]) => [x * width, y * height]);
@@ -111,6 +140,10 @@
context.moveTo(...a); context.lineTo(...b); context.lineTo(...c); context.closePath();
context.fillStyle = `rgba(${pigment},${.012 + light * .025})`;
context.fill();
+ context.fillStyle = surface;
+ context.globalAlpha = .65 + light * .35;
+ context.fill();
+ context.globalAlpha = 1;
context.save(); context.clip();
const offset = (shard.tint - .5) * 14;
for (let channel = 0; channel < 4; channel++) {
diff --git a/deploy/site/index.html b/deploy/site/index.html
index 6fbb558..6671193 100644
--- a/deploy/site/index.html
+++ b/deploy/site/index.html
@@ -81,7 +81,7 @@ footer .icon{width:11px;height:11px;vertical-align:-1px;margin-right:.6ch}
source
-
+