If you have a coffee cup on a table in VR, is that coffee cup a child of the table? How do you move the coffee cup off the table and put it onto another table? Is it now a child of that other table? What about the coffee in the cup? Is that a child of the cup? How do you change properties of the coffee without necessarily accessing the table and the cup?
Developers working on 3D systems have developed much better paradigms than the DOM for dealing with this problem. An Entity-Component-System architecture with "constraints" is the current best solution. In that architecture, you would create a coffee cup "entity" with a mesh "component" with another "constraint" component, constraining that coffee cup to the table (or better yet, mass component acted on by a physics system). Then you can simply remove the constraint component when removing the cup from one table, and re-add the constraint component when adding it to the other table.
Overall, I think web developers are in for some intense learning and paradigm shifts if 3D becomes the norm.
As for the gorilla-banana problem, I would think all objects in a scene would be under the root, with the exception of pieces that make up a thing and rarely separate (wheels on a car, for example).
Additionally, you can throw OOP in that mix as well, because Three.js has it's own whole OOP-style framework, that you're strapping declarative React on top of with this renderer. Reminds me of Jonathan Blow's talk on the end of civilization via endless layers of abstraction[1].
I really think, when it's ready, a Bevy[2]-style system either native or compiled to WASM with WebGPU will be ideal.
And while I'm airing opinions (forgive me), I think writing shaders now is like SQL 30 years ago. Developers left optimizing difficult--according to them--SQL to database administrators by abstracting it away into ORMs. If history is any indicator, I think we'll be having the same arguments on Hacker News 30 years from now about 3D frameworks vs writing shaders directly as we're having now about ORMs vs writing SQL directly.
This provides tons of benefits, so for example you can also decide to iterate over the entites by shader program and gain significant speedups for graphics processing, or maintain components that roughly sort them by their position in world space for physics and culling or lighting, etc.
For a crude analogy, imagine if Document.querySelectorAll() were a zero-cost abstraction, i.e. it ran as fast as iterating over linear memory. In practice this isn't how it turns out with an ECS, but it's much closer and you can get this kind of performance for the "hot path" kind of queries.
To add to the sibling comment, there's another wonderful Rust ECS called shipyard[0] and I helped write a scenegraph for it (which I really need to update, one of these days)[1]
There's some excellent demos of how this works with this library with a full physics engine. Loads great even on my phone.
Let's say you're building a game where you want a sphere to stick to whatever player you throw it at. How would you do that with a scene graph/OOP model? It'd be awkward, removing objects from one parent and adding them to another. Even more awkward if it's a complex object and you only want a part of that complex object to stick to the player. ECS + a constraint or physics system does a decent job (not perfect) of handling this in a relatively elegant and performant way.
I've used Three.js enough--built my portfolio[1] out of it, and then switched to Babylon when I realized how little I liked Three.js. For the record, I also dislike Babylon.
could you go more into detail what you mean when you say "anything non trivial"? is there a real example of something that would not be possible to create in, say, threejs?
Benefits include complete control at frame and pixel level, being cross-platform (same code runs on web, iOS, macOS, Linux), and having access to third-party C/C++ libraries for 3D graphics.
There's some overhead but it's negligible (assuming you're not making overly redundant API calls.)
If your data isn't structured for fast rendering, it doesn't matter much what language you're using; they'll all be too slow.
[0] https://github.com/emscripten-core/emscripten/blob/main/src/... [1] https://github.com/emscripten-core/emscripten/blob/main/test...
Desktop GL emulation is just a layer on top OpenGL ES if, for example, you're still using OpenGL's fixed function pipeline (deprecated 13 years ago.)
A C++ application compiled via Emscripten ships (a fairly large amount) of JS glue code that exposes all relevant Browser APIs like WebGL, Fetch or other HTML5 stuff to the actual WASM program. As others commented, for WebGL an additional API translation is applied. If the source targets OpenGL ES 2 (or 3 for WebGL 2), this step has almost no overhead however.
The idea is that it does more cacheing of things like uniform locations and such so you do very fast in-memory lookups in WASM without hitting the JS Api as much.
In the future this will be obsolete since WebGPU has a more optimal API to begin with, and Rust/WASM won't need to go through the JS layer due to "interface types"
The underlying abstraction model of having a tree of components and re-rendering only the parts that have changed between renders doesn’t map to the hardware at all, meaning you’ll waste most of the HW performance just on maintaining the abstraction.
You’ll also get zero benefits from the third-party libraries - there’s nothing in them that can help you with stuff that matters, like minimizing amount of the GPU state transitions for example or minimizing amount of GPU/CPU syncs.
It will be scenegraphs all over again, and the graphics industry has ditched these long ago in favor of simpler models, for good reasons.
Long story short, the happy path in graphics programming is very narrow and fragile, and you typically want to structure your abstraction around it.
We switched https://flux.ai from vanilla ThreeJS to R3F and it’s been a huge productivity gain for the whole team!
Less code, that is more capable and more reusable!
In case anyone is interested, we are hiring: https://coda.io/@flux-ai/flux-jobs
PCB layouting hasn’t publicly shipped yet though
three.js isn't dom elements updated in js. The state of each object is updated in the scene depending on more than whether they changed.
Where three.js lacks abstraction is a component system, in plain js, to organise application with decent patterns. Most three apps are a big blob or code.