Greatest 3D engine on the web

Ok, I must admit that the objective of the title is to catch attention, but I do sincerely believe that BabylonJS has a good shot at that title!

That being said, I wanted to list what would be some of the characteristics that, using currently available web technologies (so WebGPU is put on the sidelines for the moment), I think would be part of such an engine:

  1. The API of the engine is accessible for the main thread and is simple to use.
  2. The CPU usage of the main thread is left to the user and used as little as possible by the Engine.
  3. The available web technologies are used to the maximum of their capacity to make the Engine as performant as possible while shielding the user from their inherent complexity.

I think that by its nature, a 3d engine should not run on the main thread (CPU intensive…).

BJS is pretty good at respecting requirement 1. and 3. and I think has a good start for 2. with the offscreen canvas, but unfortunately the usage of the offscreen canvas does not meet 1. and 3.

offscreenCanvas clearly demonstrates the power of webworkers but at the same time says:

The main caveat of using Babylon.js with an offscreen canvas in a worker thread is that you will need to do special work to communicate with the engine from the main thread. You will have to use the same messaging API we used before to communicate between threads.

The reality is that WebWorkers are inherently hard to use well and the technologies to make them useful is complex (messaging, sharedworkers, sharedarraybuffers, etc.), although some tools like ComLink(GitHub - GoogleChromeLabs/comlink: Comlink makes WebWorkers enjoyable.) can make life easier. So a lot of casual web developers don’t have easily access to using this technology (you likely need a team of dev or lots of time on your hands…).

It would be great if BJS could have a special engine mode that fully handles the webworkers and the messaging associated to them and present a simple API to the users. That way web users could benefit from a great 3d engine without having to fall in the complexity of webworkers, respecting points 1, 2, and 3 that I mentioned.

A good first step could be to have a playground option that makes the code execute inside a webworker using an offscreen canvas and make parts of the API gradually supported by that webworker playground. And then eventually finding a clean way to make it directly accessible to users. (a good stackoverflow on this)

Of course WebXR support would be a must!

Oculus Quest, 1 & 2 and Hololens 2, are mobile technologies and WebWorker are especially useful in there. These technologies are mobile but at the same time are the ones making the most use of 3D, covering the full vision of the user. So a web 3d engine working at maximum capacity would be incredible, and I think BabylonJS is the best candidate!

I know this is a hard a complex feature to do well, but if somebody can pull it off, the BJS team is the one I bet on! :smiley:

1 Like

This is something that literally haunts my nights. We tried so many things on that topic. We tried to stored meshes and objects using SharedArrayBuffer but it was dead slow

Messaging is even slower…

The only hope I have is to convince edge and chrome to let us create threads


Just out of curiosity, lets say we have a playground that the code runs in a worker and uses an offscreen canvas. Mouse events are passed as messages using something like comlink, same thing with xr data. What are the main things that would be missing in that playground worker? (I understand that users would have to do a special HTML, but for the moment, lets pretend this is done in this worker playground). Of course, mesh loading and the rest would also have to happen in the playground worker.

Regarding messaging speed, this article could be interesting.

postMessage is not slow per se but serializing data to post message them is the culprit

You can run everything in the worker from a scene rendering standpoint. The only missing piece are the user inputs

1 Like

Ok, but if the shared data is only the mouse events on the canvas, and the info data of webxr. All the rest is done whitin the BJS worker, including loading data. The idea being that anything BJS happens in the worker (PG with worker being a good test candidate for this since its already isolated from any user DOM), wouldn’t that work directly? Other than for UI, there is not a lot of reason to share data with the DOM, and with XR we are already restricted to not use the DOM. Also the article I mentioned previously had some interesting info on message speed:

This changes when you have JS-driven animations running. The RAIL budget for animations is 16ms, as the visuals need to get updated every frame. If we send a message from the worker that would block the main thread for longer than that, we are in trouble. Looking at the numbers from our benchmarks, everything up to 10KiB will not pose a risk to your animation budget.

Imagine we use x and y values for mouse interaction plus a flag for the mouse buttons state, to make the message as small as possible, combine all of this in a single number to pass around. In this example the payload budget is literally a few bytes, which would be based on the article mentioned between 100 to 300 microseconds.

I would love to see the offscreen canvas example of the Helmet running in a Playground worker with orbiting mouse camera interaction if that works well it would be a good proof of concept, then add keyboard, and then do the same with XR (which would be a bit more tricky).

Well it is not in the PG, but we have the running example here of a scene entirely running in the offscreen canvas: Babylon.js - Worker mode

The missing piece is only event propagation and we chatted about it there: Support for offscreen canvas - Announcements - Babylon.js

By the way, the Playground is a React app so if you are motivated to tech a stab at it, I’m all for having an option (off by default) to run the rendering part in an offscreen canvas

Thanks I will definitely take a look, I think BJS on worker is worth testing and retesting until we have a solution. Might also take the opportunity to add right-side coding :-).