myco.systems/public/script.js
Brooke e359e56396
All checks were successful
Hugo / build (push) Successful in 22s
remove comments
2024-03-14 17:49:53 -04:00

103 lines
No EOL
3.3 KiB
JavaScript
Executable file

(function () {
"use strict";
const enc = (x) =>
((x & 0x08) << 3) | ((x & 0x70) >> 1) | (x & 0x87) | 0x2800;
const row = (x) => String.fromCharCode(...Array.from(x, enc));
const create = (width, height) =>
Array.from(Array(height >> 2), () => new Uint8Array(width >> 1));
const set = (table, x, y) =>
(table[y >> 2][x >> 1] |= 1 << ((y & 3) | ((x & 1) << 2)));
const render = (table) => table.map(row).join("\n");
const frame = () => new Promise((resolve) => requestAnimationFrame(resolve));
const element = (name, options) =>
Object.assign(document.createElement(name), options);
const bayer = (order, x, y) => {
let z = 0;
for (let i = order; i--; x >>= 1, y >>= 1)
z = ((((x & 1) ^ (y & 1)) | (z << 1)) << 1) | (y & 1);
return z;
};
const lut = (order) => {
const size = 1 << order,
area = size * size;
const lut = new Float32Array(area);
for (let y = 0; y < size; y++)
for (let x = 0; x < size; x++)
lut[x + y * size] = (bayer(order, x, y) + 0.5) / area;
return (x, y) => lut[(x % size) + (y % size) * size];
};
const simplex = new SimplexNoise();
const bayer4 = lut(4);
const fbm = (freq, amp, x, y, z) =>
simplex.noise3D(x * (freq *= 2), y * freq, z * freq) * (amp /= 2) +
simplex.noise3D(x * (freq *= 2), y * freq, z * freq) * (amp /= 2) +
simplex.noise3D(x * (freq *= 2), y * freq, z * freq) * (amp /= 2) +
simplex.noise3D(x * (freq *= 2), y * freq, z * freq) * (amp /= 2) +
simplex.noise3D(x * (freq *= 2), y * freq, z * freq) * (amp /= 2) +
simplex.noise3D(x * (freq *= 2), y * freq, z * freq) * (amp /= 2) +
simplex.noise3D(x * (freq *= 2), y * freq, z * freq) * (amp /= 2) +
simplex.noise3D(x * (freq *= 2), y * freq, z * freq) * (amp /= 2);
const texture = (u, v, w) => (2 * (0.5 + 0.5 * fbm(0.5, 1, u, v, w))) % 1;
const globe = (x, y, u, v, w) => {
const d = u * u + v * v;
if (d > 1) return false;
const f = 1 / ((1 - d ** 0.5) ** 0.5 + 1);
const t = texture(1e-1 * w + f * u, f * v, 1e-2 * w);
return t > bayer4(x, y);
};
const main = async () => {
const fillerSize = 100;
const filler =
"\u28ff".repeat(fillerSize) + "\n\u28ff".repeat(fillerSize - 1);
const root = element("div", { className: "braille" });
const hidden = element("div", { className: "hidden", textContent: filler });
const visible = element("div", { className: "visible" });
root.appendChild(hidden);
root.appendChild(visible);
document.body.appendChild(root);
for (; ; await frame()) {
const hr = hidden.getBoundingClientRect();
const fontWidth = hr.width / fillerSize;
const fontHeight = hr.height / fillerSize;
const rr = root.getBoundingClientRect();
const ratio = rr.width / rr.height;
const width = (rr.width / fontWidth) << 2;
const height = (rr.height / fontHeight) << 3;
const pixels = create(width, height);
const time = 1e-3 * Date.now();
for (let y = 0; y < height; y++) {
const v = (2 * y) / height - 1;
for (let x = 0; x < width; x++) {
const u = ratio * ((2 * x) / width - 3.3);
const shiftedU = u + 1.2;
if (globe(x, y, shiftedU, v, time)) set(pixels, x, y);
}
}
visible.textContent = render(pixels);
}
};
main();
})();