diff --git a/TODO.txt b/TODO.txt
index d4b9f6d..19679d7 100644
--- a/TODO.txt
+++ b/TODO.txt
@@ -1,4 +1,19 @@
TODO:
+ Make sure component works right
+ bundled, of course
+ webpack?
+ Minimum react requirement?
+ Move off of regl
+ Unify implementations?
+ Responsive changes
+ Move start time to rain object
+ Matrix component should record, then overwrite it
+ Reshape all passes to react to config changes, ie. "configure"
+ main.js "formulate" --> "configure"
+ simple deltas only require updating the uniforms
+ return boolean of whether all deltas are simple
+ Resource changes are simple if they're cached and loaded, false otherwise
+ remake the pipeline if anything returns false
Create multiple distributions
core
One embedded MSDF, combined from the two main glyph sets and their configs
@@ -7,7 +22,6 @@ TODO:
and then one with built-in MSDF generation
(TTF + glyphString) --> MSDF
Is MSDF strictly necessary?
- Move off of regl
Expanded configurability
Modify regl pass
async build(config, inputs)
diff --git a/js/Matrix.js b/js/Matrix.js
index 6a8a2a9..13f6453 100644
--- a/js/Matrix.js
+++ b/js/Matrix.js
@@ -112,7 +112,9 @@ export const Matrix = memo((props) => {
const [rRenderer, setRenderer] = useState(null);
const [rRain, setRain] = useState(null);
- const configProps = Object.fromEntries(Object.entries(rawConfigProps).filter(([_, value]) => value != null));
+ const configProps = Object.fromEntries(
+ Object.entries(rawConfigProps).filter(([_, value]) => value != null),
+ );
const supportsWebGPU = () => {
return (
@@ -155,7 +157,12 @@ export const Matrix = memo((props) => {
setCanvas(canvas);
const loadRain = async () => {
- const renderer = await import(`./${useWebGPU ? "webgpu" : "regl"}/main.js`);
+ let renderer;
+ if (useWebGPU) {
+ renderer = await import("./webgpu/main.js");
+ } else {
+ renderer = await import("./regl/main.js");
+ }
setRenderer(renderer);
const rain = await renderer.init(canvas);
setRain(rain);
diff --git a/js/bundle-contents.js b/js/bundle-contents.js
index ef1adf5..93c2943 100644
--- a/js/bundle-contents.js
+++ b/js/bundle-contents.js
@@ -2,7 +2,4 @@ import { Matrix } from "./Matrix";
import inclusions from "./inclusions";
import * as reglRenderer from "./regl/main";
import * as webgpuRenderer from "./webgpu/main";
-globalThis.inclusions = inclusions;
-globalThis.reglRenderer = reglRenderer;
-globalThis.webgpuRenderer = webgpuRenderer;
-globalThis.Matrix = Matrix;
+export { inclusions, reglRenderer, webgpuRenderer, Matrix };
diff --git a/js/fetchLibraries.js b/js/fetchLibraries.js
index c68bd01..2620684 100644
--- a/js/fetchLibraries.js
+++ b/js/fetchLibraries.js
@@ -1,9 +1,10 @@
export default async () => {
- let glMatrix, createREGL;
+ let glMatrix, createREGL, inclusions;
try {
glMatrix = await import("gl-matrix");
createREGL = (await import("regl")).default;
+ inclusions = (await import("./inclusions.js")).default;
} catch {
const loadJS = (src) =>
new Promise((resolve, reject) => {
@@ -14,7 +15,8 @@ export default async () => {
await Promise.all([loadJS("lib/regl.min.js"), loadJS("lib/gl-matrix.js")]);
glMatrix = globalThis.glMatrix;
createREGL = globalThis.createREGL;
+ inclusions = [];
}
- return { glMatrix, createREGL };
+ return { glMatrix, createREGL, inclusions };
};
diff --git a/js/inclusions.js b/js/inclusions.js
index 318855c..1e14e2d 100644
--- a/js/inclusions.js
+++ b/js/inclusions.js
@@ -1,75 +1,74 @@
-import highPassFrag from "../shaders/glsl/bloomPass.highPass.frag.glsl";
-import blurFrag from "../shaders/glsl/bloomPass.blur.frag.glsl";
-import combineFrag from "../shaders/glsl/bloomPass.combine.frag.glsl";
-import imagePassFrag from "../shaders/glsl/imagePass.frag.glsl";
-import mirrorPassFrag from "../shaders/glsl/mirrorPass.frag.glsl";
-import palettePassFrag from "../shaders/glsl/palettePass.frag.glsl";
-import rainPassIntro from "../shaders/glsl/rainPass.intro.frag.glsl";
-import rainPassRaindrop from "../shaders/glsl/rainPass.raindrop.frag.glsl";
-import rainPassSymbol from "../shaders/glsl/rainPass.symbol.frag.glsl";
-import rainPassEffect from "../shaders/glsl/rainPass.effect.frag.glsl";
-import rainPassVert from "../shaders/glsl/rainPass.vert.glsl";
-import rainPassFrag from "../shaders/glsl/rainPass.frag.glsl";
-import stripePassFrag from "../shaders/glsl/stripePass.frag.glsl";
-import msdfCoptic from "../assets/coptic_msdf.png";
-import msdfGothic from "../assets/gothic_msdf.png";
-import msdfMatrixCode from "../assets/matrixcode_msdf.png";
-import msdfRes from "../assets/resurrections_msdf.png";
-// import megacity from "../assets/megacity_msdf.png";
-import msdfResGlint from "../assets/resurrections_glint_msdf.png";
-// import msdfHuberfishA from "../assets/huberfish_a_msdf.png";
-// import msdfHuberfishD from "../assets/huberfish_d_msdf.png";
-// import msdfGtargTenretni from "../assets/gtarg_tenretniolleh_msdf.png";
-// import msdfGtargAlienText from "../assets/gtarg_alientext_msdf.png";
-// import msdfNeoMatrixology from "../assets/neomatrixology_msdf.png";
-// import texSand from "../assets/sand.png";
-// import texPixels from "../assets/pixel_grid.png";
-import texMesh from "../assets/mesh.png";
-import texMetal from "../assets/metal.png";
-import bloomBlurShader from "../shaders/wgsl/bloomBlur.wgsl";
-import bloomCombineShader from "../shaders/wgsl/bloomCombine.wgsl";
-import endPassShader from "../shaders/wgsl/endPass.wgsl";
-import imagePassShader from "../shaders/wgsl/imagePass.wgsl";
-import mirrorPassShader from "../shaders/wgsl/mirrorPass.wgsl";
-import palettePassShader from "../shaders/wgsl/palettePass.wgsl";
-import rainPassShader from "../shaders/wgsl/rainPass.wgsl";
-import stripePassShader from "../shaders/wgsl/stripePass.wgsl";
-
export default [
- highPassFrag,
- blurFrag,
- combineFrag,
- imagePassFrag,
- mirrorPassFrag,
- palettePassFrag,
- rainPassIntro,
- rainPassRaindrop,
- rainPassSymbol,
- rainPassEffect,
- rainPassVert,
- rainPassFrag,
- stripePassFrag,
- msdfCoptic,
- msdfGothic,
- msdfMatrixCode,
- msdfRes,
- // megacity,
- msdfResGlint,
- // msdfHuberfishA,
- // msdfHuberfishD,
- // msdfGtargTenretni,
- // msdfGtargAlienText,
- // msdfNeoMatrixology,
- // texSand,
- // texPixels,
- texMesh,
- texMetal,
- bloomBlurShader,
- bloomCombineShader,
- endPassShader,
- imagePassShader,
- mirrorPassShader,
- palettePassShader,
- rainPassShader,
- stripePassShader,
+ [
+ "import::shaders/glsl/bloomPass.highPass.frag.glsl",
+ () => import("../shaders/glsl/bloomPass.highPass.frag.glsl"),
+ ],
+ [
+ "import::shaders/glsl/bloomPass.blur.frag.glsl",
+ () => import("../shaders/glsl/bloomPass.blur.frag.glsl"),
+ ],
+ [
+ "import::shaders/glsl/bloomPass.combine.frag.glsl",
+ () => import("../shaders/glsl/bloomPass.combine.frag.glsl"),
+ ],
+ ["import::shaders/glsl/imagePass.frag.glsl", () => import("../shaders/glsl/imagePass.frag.glsl")],
+ [
+ "import::shaders/glsl/mirrorPass.frag.glsl",
+ () => import("../shaders/glsl/mirrorPass.frag.glsl"),
+ ],
+ [
+ "import::shaders/glsl/palettePass.frag.glsl",
+ () => import("../shaders/glsl/palettePass.frag.glsl"),
+ ],
+ [
+ "import::shaders/glsl/rainPass.intro.frag.glsl",
+ () => import("../shaders/glsl/rainPass.intro.frag.glsl"),
+ ],
+ [
+ "import::shaders/glsl/rainPass.raindrop.frag.glsl",
+ () => import("../shaders/glsl/rainPass.raindrop.frag.glsl"),
+ ],
+ [
+ "import::shaders/glsl/rainPass.symbol.frag.glsl",
+ () => import("../shaders/glsl/rainPass.symbol.frag.glsl"),
+ ],
+ [
+ "import::shaders/glsl/rainPass.effect.frag.glsl",
+ () => import("../shaders/glsl/rainPass.effect.frag.glsl"),
+ ],
+ ["import::shaders/glsl/rainPass.vert.glsl", () => import("../shaders/glsl/rainPass.vert.glsl")],
+ ["import::shaders/glsl/rainPass.frag.glsl", () => import("../shaders/glsl/rainPass.frag.glsl")],
+ [
+ "import::shaders/glsl/stripePass.frag.glsl",
+ () => import("../shaders/glsl/stripePass.frag.glsl"),
+ ],
+ ["import::assets/coptic_msdf.png", () => import("../assets/coptic_msdf.png")],
+ ["import::assets/gothic_msdf.png", () => import("../assets/gothic_msdf.png")],
+ ["import::assets/matrixcode_msdf.png", () => import("../assets/matrixcode_msdf.png")],
+ ["import::assets/resurrections_msdf.png", () => import("../assets/resurrections_msdf.png")],
+ ["import::assets/megacity_msdf.png", () => import("../assets/megacity_msdf.png")],
+ [
+ "import::assets/resurrections_glint_msdf.png",
+ () => import("../assets/resurrections_glint_msdf.png"),
+ ],
+ ["import::assets/huberfish_a_msdf.png", () => import("../assets/huberfish_a_msdf.png")],
+ ["import::assets/huberfish_d_msdf.png", () => import("../assets/huberfish_d_msdf.png")],
+ [
+ "import::assets/gtarg_tenretniolleh_msdf.png",
+ () => import("../assets/gtarg_tenretniolleh_msdf.png"),
+ ],
+ ["import::assets/gtarg_alientext_msdf.png", () => import("../assets/gtarg_alientext_msdf.png")],
+ ["import::assets/neomatrixology_msdf.png", () => import("../assets/neomatrixology_msdf.png")],
+ ["import::assets/sand.png", () => import("../assets/sand.png")],
+ ["import::assets/pixel_grid.png", () => import("../assets/pixel_grid.png")],
+ ["import::assets/mesh.png", () => import("../assets/mesh.png")],
+ ["import::assets/metal.png", () => import("../assets/metal.png")],
+ ["import::shaders/wgsl/bloomBlur.wgsl", () => import("../shaders/wgsl/bloomBlur.wgsl")],
+ ["import::shaders/wgsl/bloomCombine.wgsl", () => import("../shaders/wgsl/bloomCombine.wgsl")],
+ ["import::shaders/wgsl/endPass.wgsl", () => import("../shaders/wgsl/endPass.wgsl")],
+ ["import::shaders/wgsl/imagePass.wgsl", () => import("../shaders/wgsl/imagePass.wgsl")],
+ ["import::shaders/wgsl/mirrorPass.wgsl", () => import("../shaders/wgsl/mirrorPass.wgsl")],
+ ["import::shaders/wgsl/palettePass.wgsl", () => import("../shaders/wgsl/palettePass.wgsl")],
+ ["import::shaders/wgsl/rainPass.wgsl", () => import("../shaders/wgsl/rainPass.wgsl")],
+ ["import::shaders/wgsl/stripePass.wgsl", () => import("../shaders/wgsl/stripePass.wgsl")],
];
diff --git a/js/index.js b/js/index.js
index 700bb7d..1ac6d09 100644
--- a/js/index.js
+++ b/js/index.js
@@ -4,7 +4,6 @@ import { createRoot } from "react-dom/client";
import { Matrix } from "./Matrix";
const root = createRoot(document.getElementById("root"));
-let idx = 1;
const versions = [
"classic",
"3d",
@@ -17,24 +16,42 @@ const versions = [
"bugs",
"morpheus",
];
+const effects = ["none", "plain", "palette", "stripes", "pride", "trans", "image", "mirror"];
const App = () => {
const [version, setVersion] = useState(versions[0]);
+ const [effect, setEffect] = useState("plain");
const [numColumns, setNumColumns] = useState(80);
const [cursorColor, setCursorColor] = useState(null);
const [backgroundColor, setBackgroundColor] = useState("0,0,0");
const [rendererType, setRendererType] = useState(null);
const [density, setDensity] = useState(2);
const [destroyed, setDestroyed] = useState(false);
- const onButtonClick = () => {
+ const onVersionButtonClick = () => {
setVersion((s) => {
- const newVersion = versions[idx];
- idx = (idx + 1) % versions.length;
- console.log(newVersion);
+ let index = versions.indexOf(version) + 1;
+ if (index === versions.length) {
+ index = 0;
+ }
+ const newVersion = versions[index];
+ console.log("version:", newVersion);
return newVersion;
});
setCursorColor(null);
setBackgroundColor(null);
};
+ const onEffectButtonClick = () => {
+ setEffect((s) => {
+ let index = effects.indexOf(effect) + 1;
+ if (index === effects.length) {
+ index = 0;
+ }
+ const newEffect = effects[index];
+ console.log("effect:", newEffect);
+ return newEffect;
+ });
+ setCursorColor(null);
+ setBackgroundColor(null);
+ };
const onRendererButtonClick = () => {
setRendererType(() => (rendererType === "webgpu" ? "regl" : "webgpu"));
};
@@ -45,7 +62,8 @@ const App = () => {
return (
Rain
-
+
+
@@ -86,6 +104,7 @@ const App = () => {
{
const libraries = await fetchLibraries();
createREGL = libraries.createREGL;
glMatrix = libraries.glMatrix;
+ inclusions = libraries.inclusions;
const resize = () => {
const devicePixelRatio = window.devicePixelRatio ?? 1;
diff --git a/js/utils/config.js b/js/utils/config.js
index 75d6918..1a03ebd 100644
--- a/js/utils/config.js
+++ b/js/utils/config.js
@@ -17,14 +17,12 @@ const fonts = {
glyphSequenceLength: 57,
glyphTextureGridSize: [8, 8],
},
- /*
megacity: {
// The glyphs seen in the film trilogy
glyphMSDFURL: "assets/megacity_msdf.png",
glyphSequenceLength: 64,
glyphTextureGridSize: [8, 8],
},
- */
resurrections: {
// The glyphs seen in the film trilogy
glyphMSDFURL: "assets/resurrections_msdf.png",
@@ -32,7 +30,6 @@ const fonts = {
glyphSequenceLength: 135,
glyphTextureGridSize: [13, 12],
},
- /*
huberfishA: {
glyphMSDFURL: "assets/huberfish_a_msdf.png",
glyphSequenceLength: 34,
@@ -58,12 +55,11 @@ const fonts = {
glyphSequenceLength: 12,
glyphTextureGridSize: [4, 4],
},
- */
};
const textureURLs = {
- // sand: "assets/sand.png",
- // pixels: "assets/pixel_grid.png",
+ sand: "assets/sand.png",
+ pixels: "assets/pixel_grid.png",
mesh: "assets/mesh.png",
metal: "assets/metal.png",
};
@@ -136,7 +132,6 @@ const defaults = {
const versions = {
classic: {},
- /*
megacity: {
font: "megacity",
animationSpeed: 0.5,
@@ -155,7 +150,6 @@ const versions = {
cursorColor: hsl(0.167, 1, 0.75),
cursorIntensity: 2,
},
- */
operator: {
cursorColor: hsl(0.375, 1, 0.66),
cursorIntensity: 3,
@@ -268,7 +262,6 @@ const versions = {
raindropLength: 0.3,
density: 0.75,
},
- /*
morpheus: {
font: "resurrections",
glintTexture: "mesh",
@@ -358,7 +351,6 @@ const versions = {
// { color: hsl(0.1, 1.0, 0.9), at: 1.0 },
],
},
- */
["3d"]: {
volumetric: true,
fallSpeed: 0.5,
diff --git a/js/webgpu/bloomPass.js b/js/webgpu/bloomPass.js
index a0767fb..d6cdf16 100644
--- a/js/webgpu/bloomPass.js
+++ b/js/webgpu/bloomPass.js
@@ -39,7 +39,7 @@ const makePyramidViews = (pyramid) => pyramid.map((tex) => tex.createView());
// The bloom pass is basically an added blur of the rain pass's high-pass output.
// The blur approximation is the sum of a pyramid of downscaled, blurred textures.
-export default ({ config, device }) => {
+export default ({ config, device, cache }) => {
const pyramidHeight = 4;
const bloomSize = config.bloomSize;
const bloomStrength = config.bloomStrength;
@@ -54,8 +54,8 @@ export default ({ config, device }) => {
}
const assets = [
- loadShader(device, "shaders/wgsl/bloomBlur.wgsl"),
- loadShader(device, "shaders/wgsl/bloomCombine.wgsl"),
+ loadShader(device, cache, "shaders/wgsl/bloomBlur.wgsl"),
+ loadShader(device, cache, "shaders/wgsl/bloomCombine.wgsl"),
];
const linearSampler = device.createSampler({
diff --git a/js/webgpu/endPass.js b/js/webgpu/endPass.js
index 0f25241..141ec7b 100644
--- a/js/webgpu/endPass.js
+++ b/js/webgpu/endPass.js
@@ -5,7 +5,7 @@ import { loadShader, makeBindGroup, makePass } from "./utils.js";
const numVerticesPerQuad = 2 * 3;
-export default ({ device, canvasFormat, canvasContext }) => {
+export default ({ device, cache, canvasFormat, canvasContext }) => {
const nearestSampler = device.createSampler();
const renderPassConfig = {
@@ -21,7 +21,7 @@ export default ({ device, canvasFormat, canvasContext }) => {
let renderPipeline;
let renderBindGroup;
- const assets = [loadShader(device, "shaders/wgsl/endPass.wgsl")];
+ const assets = [loadShader(device, cache, "shaders/wgsl/endPass.wgsl")];
const loaded = (async () => {
const [imageShader] = await Promise.all(assets);
diff --git a/js/webgpu/imagePass.js b/js/webgpu/imagePass.js
index f75de8d..fc4dbf1 100644
--- a/js/webgpu/imagePass.js
+++ b/js/webgpu/imagePass.js
@@ -17,7 +17,7 @@ export default ({ config, cache, device }) => {
const bgURL = "bgURL" in config ? config.bgURL : defaultBGURL;
const assets = [
loadTexture(device, cache, bgURL),
- loadShader(device, "shaders/wgsl/imagePass.wgsl"),
+ loadShader(device, cache, "shaders/wgsl/imagePass.wgsl"),
];
const linearSampler = device.createSampler({
diff --git a/js/webgpu/main.js b/js/webgpu/main.js
index 6030d2e..1fe7fd3 100644
--- a/js/webgpu/main.js
+++ b/js/webgpu/main.js
@@ -24,11 +24,12 @@ const effects = {
mirror: makeMirrorPass,
};
-let glMatrix;
+let glMatrix, inclusions;
export const init = async (canvas) => {
const libraries = await fetchLibraries();
glMatrix = libraries.glMatrix;
+ inclusions = libraries.inclusions;
const resize = () => {
const devicePixelRatio = window.devicePixelRatio ?? 1;
diff --git a/js/webgpu/mirrorPass.js b/js/webgpu/mirrorPass.js
index e5ec465..3dc929a 100644
--- a/js/webgpu/mirrorPass.js
+++ b/js/webgpu/mirrorPass.js
@@ -24,8 +24,8 @@ window.onclick = (e) => {
touchesChanged = true;
};
-export default ({ config, device, cameraTex, cameraAspectRatio, timeBuffer }) => {
- const assets = [loadShader(device, "shaders/wgsl/mirrorPass.wgsl")];
+export default ({ config, device, cache, cameraTex, cameraAspectRatio, timeBuffer }) => {
+ const assets = [loadShader(device, cache, "shaders/wgsl/mirrorPass.wgsl")];
const linearSampler = device.createSampler({
magFilter: "linear",
diff --git a/js/webgpu/palettePass.js b/js/webgpu/palettePass.js
index 3aca409..0872da9 100644
--- a/js/webgpu/palettePass.js
+++ b/js/webgpu/palettePass.js
@@ -73,7 +73,7 @@ const makePalette = (device, paletteUniforms, entries) => {
// won't persist across subsequent frames. This is a safe trick
// in screen space.
-export default ({ config, device, timeBuffer }) => {
+export default ({ config, device, cache, timeBuffer }) => {
const linearSampler = device.createSampler({
magFilter: "linear",
minFilter: "linear",
@@ -86,7 +86,7 @@ export default ({ config, device, timeBuffer }) => {
let output;
let screenSize;
- const assets = [loadShader(device, "shaders/wgsl/palettePass.wgsl")];
+ const assets = [loadShader(device, cache, "shaders/wgsl/palettePass.wgsl")];
const loaded = (async () => {
const [paletteShader] = await Promise.all(assets);
diff --git a/js/webgpu/rainPass.js b/js/webgpu/rainPass.js
index 497bd90..e9e2a5f 100644
--- a/js/webgpu/rainPass.js
+++ b/js/webgpu/rainPass.js
@@ -39,7 +39,7 @@ export default ({ config, glMatrix, cache, device, timeBuffer }) => {
loadTexture(device, cache, config.glintMSDFURL),
loadTexture(device, cache, config.baseTextureURL, false, true),
loadTexture(device, cache, config.glintTextureURL, false, true),
- loadShader(device, "shaders/wgsl/rainPass.wgsl"),
+ loadShader(device, cache, "shaders/wgsl/rainPass.wgsl"),
];
// The volumetric mode multiplies the number of columns
diff --git a/js/webgpu/stripePass.js b/js/webgpu/stripePass.js
index 79ab6f3..289a02a 100644
--- a/js/webgpu/stripePass.js
+++ b/js/webgpu/stripePass.js
@@ -43,7 +43,7 @@ const numVerticesPerQuad = 2 * 3;
// won't persist across subsequent frames. This is a safe trick
// in screen space.
-export default ({ config, device, timeBuffer }) => {
+export default ({ config, device, cache, timeBuffer }) => {
// Expand and convert stripe colors into 1D texture data
const stripeColors =
"stripeColors" in config
@@ -68,7 +68,7 @@ export default ({ config, device, timeBuffer }) => {
let output;
let screenSize;
- const assets = [loadShader(device, "shaders/wgsl/stripePass.wgsl")];
+ const assets = [loadShader(device, cache, "shaders/wgsl/stripePass.wgsl")];
const loaded = (async () => {
const [stripeShader] = await Promise.all(assets);
diff --git a/js/webgpu/utils.js b/js/webgpu/utils.js
index 2e286f2..4f7efe9 100644
--- a/js/webgpu/utils.js
+++ b/js/webgpu/utils.js
@@ -62,7 +62,11 @@ const makeComputeTarget = (device, size, mipLevelCount = 1) =>
GPUTextureUsage.STORAGE_BINDING,
});
-const loadShader = async (device, url) => {
+const loadShader = async (device, cache, url) => {
+ const key = url;
+ if (cache.has(key)) {
+ return cache.get(key);
+ }
const response = await fetch(url);
const code = await response.text();
return {
diff --git a/package.json b/package.json
index debad07..1bbee14 100644
--- a/package.json
+++ b/package.json
@@ -1,10 +1,21 @@
{
- "name": "react-matrix-rain",
- "version": "1.0.0",
- "description": "web-based green code rain, made with love, for react",
- "main": "dist/index.cjs.js",
+ "name": "digital-rain",
+ "version": "0.1.0",
+ "description": "web-based green code rain, made with love",
+ "type": "module",
+ "main": "./dist/digital-rain.cjs",
+ "module": "./dist/digital-rain.module.js",
+ "exports": {
+ ".": {
+ "import": "./dist/digital-rain.module.js",
+ "require": "./dist/digital-rain.cjs"
+ }
+ },
"files": [
- "/dist"
+ "/dist",
+ "LICENSE",
+ "package.json",
+ "README.md"
],
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
@@ -12,12 +23,35 @@
"start": "npm run format ; webpack serve --config ./webpack.config.js",
"build": "npm run format ; rollup -c"
},
- "keywords": [],
- "author": "",
- "license": "ISC",
+ "keywords": [
+ "rain",
+ "matrix",
+ "javascript",
+ "webgl",
+ "webgl-computer-graphics",
+ "matrix-rain",
+ "matrix-digital-rain"
+ ],
+ "author": {
+ "name": "Rezmason",
+ "url": "https://rezmason.net"
+ },
+ "contributors": [
+ {
+ "name": "nohren"
+ }
+ ],
+ "homepage": "https://github.com/Rezmason/matrix",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/Rezmason/matrix"
+ },
+ "bugs": {
+ "url": "https://github.com/Rezmason/matrix/issues"
+ },
+ "license": "MIT",
"dependencies": {
"gl-matrix": "^3.4.3",
- "holoplay-core": "^0.0.9",
"regl": "^2.1.0"
},
"devDependencies": {
@@ -46,5 +80,13 @@
"peerDependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
+ },
+ "peerDependenciesMeta": {
+ "react": {
+ "optional": true
+ },
+ "react-dom": {
+ "optional": true
+ }
}
}
diff --git a/rollup.config.mjs b/rollup.config.mjs
index cc77b43..e5a12b2 100644
--- a/rollup.config.mjs
+++ b/rollup.config.mjs
@@ -8,40 +8,65 @@ import terser from "@rollup/plugin-terser";
import { string } from "rollup-plugin-string";
import image from "@rollup/plugin-image";
-export default {
- input: "js/bundle-contents.js",
- external: ["react", "react-dom"], // keep them out of your bundle
- plugins: [
- peerDepsExternal(), // auto-exclude peerDeps
- nodeResolve(), // so Rollup can find deps in node_modules
- string({ include: ["**/*.glsl"] }),
- string({ include: ["**/*.wgsl"] }),
- image({ include: ["**/*.png"], limit: 0 }),
- babel({
- exclude: "node_modules/**", // transpile JSX
- babelHelpers: "bundled",
- presets: ["@babel/preset-react", "@babel/preset-env"],
- }),
- commonjs(), // turn CJS deps into ES
- terser({
- sourceMap: false, // <- suppress .map generation
- format: { comments: false },
- }),
- visualizer({
- filename: "dist/stats.html",
- gzipSize: true,
- brotliSize: true,
- includeAssets: true,
- }), // bundle-size treemap
- ],
- output: [
- {
+export default [
+ {
+ input: "js/bundle-contents.js",
+ external: ["react", "react-dom"], // keep them out of your bundle
+ plugins: [
+ peerDepsExternal(), // auto-exclude peerDeps
+ nodeResolve(), // so Rollup can find deps in node_modules
+ string({ include: ["**/*.glsl"] }),
+ string({ include: ["**/*.wgsl"] }),
+ image({ include: ["**/*.png"], limit: 0 }),
+ babel({
+ exclude: "node_modules/**", // transpile JSX
+ babelHelpers: "bundled",
+ presets: ["@babel/preset-react", "@babel/preset-env"],
+ }),
+ commonjs(), // turn CJS deps into ES
+ terser({
+ sourceMap: false, // <- suppress .map generation
+ format: { comments: false },
+ }),
+ visualizer({
+ filename: "dist/stats.html",
+ gzipSize: true,
+ brotliSize: true,
+ includeAssets: true,
+ }), // bundle-size treemap
+ ],
+ output: {
inlineDynamicImports: true,
- file: "dist/index.cjs.js",
+ file: "dist/digital-rain.cjs.js",
format: "cjs",
exports: "named",
sourcemap: false,
},
- // { file: 'dist/index.esm.js', format: 'es' } // optional ESM build
- ],
-};
+ },
+ {
+ input: "js/bundle-contents.js",
+ external: ["react", "react-dom"], // keep them out of your bundle
+ plugins: [
+ peerDepsExternal(), // auto-exclude peerDeps
+ nodeResolve(), // so Rollup can find deps in node_modules
+ string({ include: ["**/*.glsl"] }),
+ string({ include: ["**/*.wgsl"] }),
+ image({ include: ["**/*.png"], limit: 0 }),
+ babel({
+ exclude: "node_modules/**", // transpile JSX
+ babelHelpers: "bundled",
+ presets: ["@babel/preset-react", "@babel/preset-env"],
+ }),
+ commonjs(), // turn CJS deps into ES
+ ],
+ output: [
+ {
+ inlineDynamicImports: true,
+ file: "dist/digital-rain.module.js",
+ format: "es",
+ exports: "named",
+ sourcemap: true,
+ },
+ ],
+ },
+];
diff --git a/webpack.config.js b/webpack.config.js
index 7887383..8684ed6 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -1,9 +1,14 @@
-const webpack = require("webpack");
-const path = require("path");
-const HtmlWebpackPlugin = require("html-webpack-plugin");
-const CopyPlugin = require("copy-webpack-plugin");
+import webpack from "webpack";
+import path from "path";
+import HtmlWebpackPlugin from "html-webpack-plugin";
+import CopyPlugin from "copy-webpack-plugin";
-module.exports = {
+import { dirname } from "node:path";
+import { fileURLToPath } from "node:url";
+
+const __dirname = dirname(fileURLToPath(import.meta.url));
+
+export default {
mode: "development",
entry: path.resolve(__dirname, "./js/index.js"),
module: {