Does Babylon.js or Three.js perform better with more meshes?

It’s really all in the title. I’d just like to know which one has better performance. Out of curosity

1 Like

Well it should not be different. Both supports instances or clone so overall it should behave the same.

Speaking for Babylon.js (I do not know 3 enough): we offer:

  • Instances
  • Clones
  • Mesh freezing
  • Material Freezing
  • SPS

So a lot of options to deal with large number of meshes

4 Likes

I recently implemented the same scene on threejs and babylonjs. The reason was that I originally picked 3 because I was familiar with it, but hit a wall when I needed to do something it doesn’t support yet (overriding materials but keeping animations/skinning). So I’ll tell my experience here, and heed that it’s just anecdotal.

TL;DR: more or less the same, but 3 is faster for the average code.

In short, 3 is faster running “out of the box”. Just loading several animated objects to a scene with a code as simple as possible was noticeably slower in BJS than in 3. It seems that 3 may have a simpler or faster logic to check what changes from frame to frame. Or perhaps the materials in BJS are by default more complex than in 3? Or is it culling? I never bothered to profile both to compare exactly why. The truth is that freezing materials (and objects, to a lesser extent, since most were dynamic in my scene) makes a large difference even in basic scenes in BJS. Anyway, once you optimize BJS the performance is comparable. It was hard for me to go below 60fps in 3, but it was quite easy in BJS. I quickly learned to ignore the FPS, implement what I wanted, and optimize later. The lingering feeling is, however, that 3 is somewhat faster.

Since I had this rare experience of implementing the same code twice, I’ll extend the comparison. BJS has much nicer documentation, although there are still large holes, which this forum solves very efficiently (thanks). The BJS HowTos are much better, 3 doesn’t have them. It’s easier to find about 3 in SO and google, though. BJS has a few high level things that are nice (the extensions). 3JS has a lot of examples that are very useful, but you have to take the code, separate what you want and use it. Often the 3rd party extensions or applications you find on github use an older version – 3JS has an API that changes often and sometimes things break. Both projects have NodeMaterials, which look very interesting, but both have almost no documentation or examples – I stay away because of that. It seems too much work to understand them (and write code for them) to use them.

Regarding the API: both are comparable in terms of difficulty and are actually not very different. 3JS is less verbose at times. It has a overrideMaterial setting, for instance; other than the missing animations, it was very easy to setup a multi-pass render:

const renderCausticPass = new RenderPass(this.scene, this.camera, this.causticMaterial); // render caustic
renderCausticPass.renderToScreen = false;

// ... 
const underwaterPass = new ShaderPass(
   new THREE.ShaderMaterial({
       uniforms: {
            causticTexture: { value: causticTarget.texture },
       }
    }
);

const finalComposer = new EffectComposer(this.renderer);
// other passes here
finalComposer.addPass(renderCausticPass);

I had expected to do something quite like this in BJS, but it turned out to be much more complex. The same code above take some 70 lines of JS, plus some extra lines in the shader, plus some extra code for each object (it takes about 20 lines to load a model, make N instances of it and set it to render in two passes), to do in BJS (but hey, in BJS it works properly). EffectComposer in 3JS handles multirender easily, but in BJS I had to explicitly do a RTT. It’s a corner case, anyway. You can probably find something that is easy in BJS and hard in threejs.

The debug layer in BJS is awesome. 3JS doesn’t have it. It makes debugging scenes MUCH easier and whoever wrote it made me a much happier person.

If anyone is interested, I’m writing this code for a project that will be open sourced. It’s not online yet but I can release both versions, BJS and 3JS. I can also profile both codes to see what are the bottlenecks, but at this point my BJS code has several optimizations. It still chokes on animating a 60k faces object (apparently this should be done in the GPU, but it takes a long time in the CPU. I didn’t have time to look at it properly yet, but I can post another thread when I do).

5 Likes

Didn’t read everything, but 3JS has, for instance, by default :

  • less accurate culling (set BJS one to bSphereOnly to get the same perf)
  • no instance WM computation in InstanceBufferGeometry, contrary to BJS
  • simpler standard materials

etc.
Actually they can have exactly the same perfs but 3JS has often the minimal-feature approach (so more complex for the user to add things then) and BJS the full-feature approach (simpler for user, unless he wants to remove some).
When you build the very same scene with exactly the same features, they both get the same performances :slight_smile:

2 Likes

What’s WM?

That confirms exactly what I experienced. And the optimization howto for BJS is nice and does a good job explaining what to do for a faster scene. But as a developer it was a bit odd to see the “same” scene much slower with BJS until I read it.

Have you all considered having some sort of “fast” mode with faster default settings? It seems that most materials can be frozen, for example, and for small scenes a simpler culling works better. It could be useful to have something like the SceneOptimizer class, or a Engine.fastMode() method. I’d be willing to implement this if you think it’s worth it.

2 Likes

I love the idea as it might push ppl away if they are not reading the doc upfront. @Deltakosh any preference ?

1 Like

Well if they don’t read the doc they won’t know about it:) so not sure it is better than just our perf doc

WM = world matrix

1 Like

Actually, there’s not a single way to optimize a scene and not a single type of optimization case : too many materials, too many effects, too many meshes, too many vertices, too many culling tests, too many whatsoever …
Each case has its own solution regarding the user expectation. And each user as his own expectation also …

You may want an accurate culling and don’t care about the material, you may want to keep the ability to update a material but don’t want instances WM to be computed for you, etc, etc.

Optimizing is often disabling features that some want to keep and others don’t.

1 Like

Thanks for all the replies! I was just wondering since I’ve been redoing my voxel engine (uses normals now) but the performance is still not very good. Using instances increase my fps by 4x.

I’m going off of these:
https://playground.babylonjs.com/#IU1JEK#9: mine, around 2500 meshes
http://mikolalysenko.github.io/MinecraftMeshes/index.html: sine terrain, not sure how many meshes, seems like a lot more.

Because we developers always read the docs :smiley:

Of course. But here’s a real user feedback: as an user I’d like to have a basic fast mode.

I’d rather use 3JS for a trivial “load the model file and render it” than BJS if I have to read the optimization docs to remember all I have to do to get 60fps, and write code to loop through objects to freeze materials. It could be a list of default on the scene or engine options, like { freezeMaterials, blockMaterialDirtyMechanism, doNotSyncBoundingInfo, cullingStrategy }, and a basicFast option that sets a bunch of defaults. SceneOptimizer is arguably much more involved to write and it exists.

1 Like

FYI: Minecraft classic (classic.minecraft.net) uses Babylon.js

You can definitively achieve the same perf as your example. There is no reason you can’t. You need to analyze the perf of your example and find the bottleneck

2 Likes

Yup, that’s what I’m going for. Without copy-pasting from it, that is.

Well I challenge that :slight_smile: By default (unless you have thousands of meshes where the features implemented by bjs to be easy to use can start slow things down) you should see no difference. For a trivial load and render there should be NO difference

2 Likes

We work hard to add doc and videos there: How To use the Node Material - Babylon.js Documentation

1 Like

I’m migrating my project from threejs, the performance on babylon is absolutely terrible.
ThreeJs is something about 10x faster, or more… I didn’t measure exactly. Loading some models on Babylon made my machine freeze (400mb obj file). And by reading this forum and other sites I even believed that babylon could be better. Now I have this big problem on my hand. You guys should stop marketing that babylon and treejs have the same performance without MAJOR adaptations.

Is your 400MB model publishable? It could be interesting for stress-tests.

Wait…this must be something else :slight_smile: Maybe we can help? This is maybe something wrong in our OBJ loader that generates too much data?

I feel like this is the root of the problem because 3 and bjs behave the same way ONLY if they have the same data :wink:

2 Likes

No offense! You can’t disrespect babylon.js like that. Babylon.js is the only open source webgl library that supports every thing other similar webgl library can do and even more. Over the past years, developers have been contributing to make the library more faster, adaptive to any platform. Babylon.js is the top choice for industrial companies. However, if you need help from this forum, you’ll have to put some respect.

cheers :slightly_smiling_face:

6 Likes

@Vinc3r it’s not publishable unfortunately, it’s a 3D model of a building used in my company, I’m not allowed to share that stuff.

@Deltakosh
Sure, I’m just loading a big model, the files are the same, three.js even has more stuff into it. I will try to apply some optimizations because the three.js viewer I’m using is not vanilla, so I supose it’s unfair to compare it. (But i didn’t expect THAT much worse performance, sometimes the chrome tab uses 6GB of RAM.)

@waverider404
Sorry if I offended you, but why are you offended? Were did I show disrespect?
I’m not saying babylon is bad, I’ve choose to change to babylon because it has several points in which is way better than 3js, but performance is a priority on my application, and right now the threejs based viewer is way better on that requirement. I already prefer babylon, but this unexpected performance problem is a pain for me.


My scene is static, only the camera moves, nothing else. I’ve a lot of meshes that are duplicated (like chairs, walls, steel beams), Maybe I can detect those meshes during loading time and use Instance Buffers?

I’m not sure that babylon only renders what is in the frustum, can anyone confirm that for me?

One other thing that I’m thinking is “partial rendering” (or pop up the objects on the screen as they load/render). I`m sure that is not a very common technique because for games that would be horrible, but for my case it’s ok to do that. I only need to mantain stable performance when the camera is moving. If image is rendering slowly that’s not a problem, I need the responsiveness.

1 Like