Just an idea. For now.
This is not a thing. I would like it to become a thing one day, if time allows, but for now I just want to get some ideas out of my head and into a place where they can be examined.
The idea is simple: a cross between Svelte and Three.js. In other words, a compiler that takes a scene graph (written in HTMLx) as input, and generates low-level WebGL code as output.
A-Frame is strong evidence that markup-driven approaches to describing 3D scenes are intuitive for authors, and practical from a performance standpoint. But A-Frame and Three.js, while truly excellent, are large frameworks (in terms of JavaScript bundle size) that are therefore unsuitable for casual or whimsical uses of WebGL.
My hypothesis is that we can make it much easier to embed 3D graphics on the web in a way that is potentially more performant than existing solutions (because compilers) at a fraction of the cost in terms of bytes, and insodoing unlock new forms of creativity.
It's entirely possible that I am completely wrong about this.
import Scene from './Scene.htmlx';const scene = new Scene({ canvas: document.querySelector('canvas'), data: { cameraPos: { x: 0, y: 0, z: -5 }, color: red } });
// later — trigger a re-render scene.set({ cameraPos: { x: -2, y: 4, z: -3 } });
We could adopt large chunks of the Svelte component API, for handling local state, lifecycle hooks and the like.
It would be pretty great if we could do this sort of thing:
this is a svelte-gl component
Err, TODO. A couple of high level thoughts though.
Firstly, the job is easier in some respects than Svelte's DOM manipulation — rather than surgically updating parts of the document, in WebGL land we just re-render the entire world on any state change.
But the flip side is that it's probably not enough to just convert each element in the graph into a draw call; we probably need to do more work up-front to figure out there are no constraint violations (e.g. in the example above, we need to ensure that
#my-boxrefers to an element that currently exists, and figure out its position so that it can be set as the target of the camera and the light. Though maybe it should be
target={boxPos}anyway).
By far the easiest way to get started — and probably the most sensible, long-term — would be to add a new compiler target within Svelte itself. That way we wouldn't need to reimplement a bunch of stuff, and the two projects would stay in sync. The danger is that the experiment doesn't pan out, and Svelte is left with a vestigial appendage, so it would require buy-in from the Svelte community. The alternative would be to extract the different compiler targets out from Svelte into separate packages (
@sveltejs/compile-dom,
@sveltejs/compile-ssr,
@sveltejs/compile-gl) that the core calls out to. I haven't looked into how feasible that would be.
requestAnimationFramewon't cut the mustard for animation helpers