diff --git a/js/Matrix.js b/js/Matrix.js index b0fbdf3..a2c3fea 100644 --- a/js/Matrix.js +++ b/js/Matrix.js @@ -1,13 +1,6 @@ -import inclusions from "./inclusions"; - import React, { useEffect, useState, useRef, memo } from "react"; -import * as reglRenderer from "./regl/main"; -import * as webgpuRenderer from "./webgpu/main"; import makeConfig from "./utils/config"; -globalThis.inclusions = inclusions; -console.log(webgpuRenderer.init, webgpuRenderer.formulate, webgpuRenderer.destroy); - /** * @typedef {object} Colour * @property {"hsl"|"rgb"} space @@ -115,33 +108,64 @@ export const Matrix = memo((props) => { const { style, className, ...rest } = props; const elProps = { style, className }; const matrix = useRef(null); - const [rain, setRain] = useState(null); + const [rCanvas, setCanvas] = useState(null); + const [rRenderer, setRenderer] = useState(null); + const [rRain, setRain] = useState(null); + + const supportsWebGPU = () => { + return ( + window.GPUQueue != null && + navigator.gpu != null && + navigator.gpu.getPreferredCanvasFormat != null + ); + }; useEffect(() => { + const useWebGPU = supportsWebGPU() && ["webgpu"].includes(rest.renderer?.toLowerCase()); + const isWebGPU = rRenderer?.type === "webgpu"; + + if (rRenderer != null && useWebGPU === isWebGPU) { + return; + } + + if (rCanvas != null) { + matrix.current.removeChild(rCanvas); + setCanvas(null); + } + + if (rRain != null) { + rRenderer?.destroy(rRain); + setRain(null); + } + + if (rRenderer != null) { + setRenderer(null); + } + const canvas = document.createElement("canvas"); - matrix.current.appendChild(canvas); canvas.style.width = "100%"; canvas.style.height = "100%"; - const init = async () => { - setRain(await reglRenderer.init(canvas)); - }; - init(); + matrix.current.appendChild(canvas); + setCanvas(canvas); - return () => { - reglRenderer.destroy(rain); - setRain(null); + const loadRain = async () => { + const renderer = await import(`./${useWebGPU ? "webgpu" : "regl"}/main.js`); + setRenderer(renderer); + const rain = await renderer.init(canvas); + setRain(rain); }; - }, []); + loadRain(); + }, [props.renderer]); useEffect(() => { - if (rain == null) { + if (rRain == null || rRain.destroyed) { return; } const refresh = async () => { - await reglRenderer.formulate(rain, makeConfig({ ...rest })); + await rRenderer.formulate(rRain, makeConfig({ ...rest })); }; refresh(); - }, [props, rain]); + }, [props, rRain]); return
; }); diff --git a/js/bundle-contents.js b/js/bundle-contents.js new file mode 100644 index 0000000..ef1adf5 --- /dev/null +++ b/js/bundle-contents.js @@ -0,0 +1,8 @@ +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; diff --git a/js/index.js b/js/index.js index 415b392..45ea819 100644 --- a/js/index.js +++ b/js/index.js @@ -1,7 +1,6 @@ import React from "react"; import { createRoot } from "react-dom/client"; import { Matrix } from "./Matrix"; -//import { Matrix } from "react-matrix-rain"; const root = createRoot(document.getElementById("root")); let idx = 1; @@ -23,6 +22,7 @@ const versions = [ const App = () => { const [version, setVersion] = React.useState(versions[0]); const [numColumns, setNumColumns] = React.useState(10); + const [rendererType, setRendererType] = React.useState(null); const onButtonClick = () => { setVersion((s) => { const newVersion = versions[idx]; @@ -36,16 +36,20 @@ const App = () => { return newColumns; }); }; + const onRendererButtonClick = () => { + setRendererType(() => (rendererType === "webgpu" ? "regl" : "webgpu")); + }; return (