'Render targets' is much slower with left-handed-system than right-handed-system

I have a project with a few hundred visible instances of an imported GLTF-mesh (actually, a low poly tree).
Since GLTF uses a right-handed coordinate system, I originally used this:

scene.useRightHandedSystem = true;

But now I’ve come to think about it, I prefer a left-handed system more, because it’s more intuitive to me, so I removed that line.

But somehow, just by removing that line, now the rendering takes a lot longer.
Render Targets in the inspector now is about 5 to 10 times as much ( was under 1 ms, and now 5 to 10 ms!).
Because of this, ‘Frame Total’ goes from 7ms to 17ms, which drops the framerate below 60.

I’m sorry for not having a playground to prove this, since the project is quite complex.

What could cause this? I really would prefer to use the default left-handed system.

It looks like the CascadedShadowGenerator is causing this. When I disable the shadows of the trees, Render Targets goes down to 0.3 ms.

But I still don’t understand why there’s such a difference between the 2 coordinate systems.

Can you repro the problem in the Playground? This seems suspicious

I tried setting up a playground, butI can’t reproduce the problem with this.
Maybe it’s the imported mesh that I’m using, so I’ll have to find a way to use this model in the playground. I don’t use github, so maybe with a public Dropbox link.

Easy peasy :grin:

Load in Blender, export as GLTF (embedded). This will export everything into a plain text file. Open with a text editor and copy contents.

Use this playground as a reference: Babylon.js Playground

Replace everything after data:

Well, it’s not the imported mesh, and neither the shadowgenerator. I disabled almost everything else too (skybox, heightmap ground) from the scene and the problem persists. The scene is now just a ground and 1000 instances of an imported mesh.

Even with instances of a simple cube mesh, the difference in Absolute FPS is 1.5 times faster with scene.useRightHandedSystem=true.

However, I can’t reproduce it yet in a playground, it only happens in my project itself. I’ll keep searching :slight_smile:

I think I found a clue!

With scene.useRightHandedSystem=true the number of Draw Calls is 1.
But without that line , the number of Draw Calls is the same as the number of active meshes!

It only happens with GLB meshes that I import with SceneLoader.ImportMeshAsync.
When I just create a mesh on the fly with MeshBuilder.CreateBox , there is no difference in FPS.

All GLB files I tried, were created with Blender export to GLTF/GLB. Maybe that causes the problem, but I have no other way to create the mesh files.

Somehow the used coordinate system in the mesh file causes the rendering to be different, with different values for scene.useRightHandedSystem .

I also tried exporting the mesh in Blender to OBJ format. This works, but this doubles the amount of vertices, and the object turns to white, instead of colors.

@Deltakosh is the hero of optimizations and I bet he ll find a fix in no time :slight_smile:

Ok hear me out lol :slight_smile:
With RH mode on, we do not change the glTF hierarchy but in LH we add a negative scale to the root node. That MAY block the instances to render correctly but I would love to see a repro to confirm :slight_smile:

Can you share a GLB that reproduces that problem?

I think the problem is because the instances don’t have the same sign for the world matrix determinant than the source mesh.

@BobDylan You should make sure that you create the instances with the same parent than the source mesh. By default, instances are created without any parent, so they won’t be under the __root__ node, which is the one responsible for the negative matrix determinant for the original mesh in LH mode. In RH mode it’s ok because this __root__ node has an identity transformation, so the determinant matrix is positive.

1 Like

Yeah this is what I wanted to check. I think this is the right one

Now I’ve come to think about it, I did move the trees to an empty treecontainer-mesh lately, because opening the Nodes tree in the inspector took too long :slight_smile: I did not do this in the playground yet, so maybe I can reproduce this, I’ll try.

I don’t really understand though, why this would make a difference for imported GLB-meshes , but not for created meshes or imported OBJ-meshes. And is this a bug or a feature ? :slight_smile:

removing this line, does not solve the problem:
newtree.parent = treecontainer;

All trees are now in the root.
The Absolute FPS is still 1,5 times better (135 vs 90) in right-handed system than in left-handed, so I doubt if the parenting causes the problem. I have no clue about transformation matrices, so I can’t find a solution right now, other than using right-handed-system.

Imported glb meshes have a parent node called __root__ that has a special transformation to deal with rhs ↔ lhs conversion that other meshes don’t have. It’s this transformation that makes the determinant of a glb mesh matrix be negative. If instances of this mesh are not under the root node, they will likely have a positive determinant matrix, meaning we are not able to draw all of them in a single draw call. Instead, we will fallback to one draw call per instance, hence the bad performances.

Ok, I understand a little bit better now. I already noticed that different file formats behave differently, which is quite confusing for a beginner (like me). I already did

const mesh = result.meshes[0];
const allMeshes = mesh.getChildMeshes();
const tree = allMeshes[0];

with GLB files but for OBJ files I just use :
const tree = result.meshes[0];

I think it’s important that this problem is resolved, because GLB is getting more and more popular, because of the single file format and default ability to render colors, without textures. (I could not get objFileLoader to work with colors with my ES6/Vite setup, because BABYLON.OBJFileLoader.IMPORT_VERTEX_COLORS = true;
is not defined then. )

Many people trying out Babylon with GLB-files could unnessecarily be disappointed with the performance, since the default is left-handed. I’d love to try the Babylon-file format, but I found the Blender exporter not very useful, I can’t seem to find where to specify to include colors or the coordinate system etc. I ended up with a half-transparent tree with red and black squares as a texture.

We believe we explained why the problem is happening but ideally it would be better if you could share your code on the playground so we can show you how to fix it.

This is an expected behavior

Here is a doc to share a playground with external assets like your glb file:

I finally managed to export the tree in Blender to Babylon format. I had to enable inline textures/materials and disable ‘Use PBR Materials’ to get it right.
Now the colors are working properly, without strange transparency issues.
Also, the Absolute FPS seems even a bit better than with using the GLB-file.

The Blender exporter also exports a .babylon.manifest file, which seems not to be used by Babylon. Any idea what this does?

Maybe the Babylon file format should be pushed a bit more, since it seems perfect, but I don’t know many people actually using it yet. An online asset store for low poly 3D objects and a good working online converter for other formats would be awesome.

More about the manifest: Babylon.js docs

1 Like