GLTFExporter GLTFLoader and InstancedBufferGeometries

Hi all.

I have realized that neither GLTFExporter neither GLTFLoader are able to export|load scenes using InstancedBufferGeometries.

Is there any plan to add this functionality to them?

Best regards

1 Like

No because it’s usually not the responsibility of loaders to care about instanced rendering. This is something the 3D engine (in our case WebGLRenderer) should do automatically. Such a feature is called auto-instancing and supported by game engines like Unreal. However, three.js is not yet able to do this.

Hi Michael.

Many thanks for your feedback.

Best regards

If you’re interested, i’m releasing the IndexedVolume component next days, it doesn’t only accelerate the culling phase but also provides auto-instancing (with culling), the impostor plugin will follow later.

Here’s a snippet I’ve used before to convert a model loaded from GLTFLoader into an InstancedBufferGeometry –

But to export you’d need to undo that. If you use multiple copies of the same BufferGeometry, GLTFExporter should be smart enough to export only one copy and reuse it, but the file format doesn’t have a GPU instancing feature as such, and InstancedBufferGeometry can’t be exported directly.


Yes, sure I am interested.

: )

I will have a look.

Many thanks.

By now I have also implemented my own culling system for instances using webworker technology.

By now I am able to see 50k meshes, 1M instances and more than 1000M vertices | 640M triangles in a normal PC.

I am quite happy but of course very interested in any other solution.

About the instancedBufferGeometries and GLTExporter and GLTLoader, I think I will manage to addapt the code to be able to enable instancing.

My idea is to save in Scene.userData my shader code and be able to use saved InstancedBufferAttributes.

Best regards

I need to add this is part of a commercial project.

You perform culling asynchronous? Culling is required to be synchronous with the current frame, otherwise objects pop in/out on screen.


I used SharedBufferArrays.

Best regards

It doesn’t matter actually if it is a shared buffer, culling is part of the render process and should be done synchronous right before the render list generated from that process is rendered. Once the frustum changes fast and the worker gets out of sync. objects will pop in/out suddenly, this effect grows with the amount of objects / the moment you would benefit from a worker.


Sorry for the delay, today I was working on other topics.

Maybe the problem is that I didn’t explained my solution with many details.

In deed, my solution used 2 levels of culling.

As you has hightlighted, the real culling is done on the main thread (in the render loop) based on a culling distance and real bounding box of each mesh (computed taking in mind the union of all boundingboxes of all instances inside each mesh.

What I do on the webworker is recompute the maxInstanceCount of each InstancedBufferGeomtery which is on Frustum and not distance culled, I do this looking in my instancedBufferAttributes passed as sharedBufferArrays. Reducing maxInstanceCount also increases the render performance and doesn’t need to be done in a synchronous way.

For me it’s working very well, but my scene doesn’t has more than 100k meshes, so maybe it is not the same problem you are facing.

In my scene I have 100k meshes and 1M of total instances, each mesh has a different number of instances and very different number of vertices. There are lots of small meshes with lots of instances distributed along a huge space and complicated meshes which doesn’t have any instance (1 occurrence) or only a few.

I hope this will explain a bit better.

Best regards and again many thanks for your help.

BTW I had a look on your work and it’s really impressive. I guess that you are not going to learn nothing from me. Anyway, if you need more information you can ping me.

: )