Performance Issues - Occlusion Culling?

Hey everyone!
I have a complex entity based game (TS with threejs and Solidjs) now with a somewhat complex level/scene.
It has lots of geometries and animations going on at the same time.
I was looking into several improvements to be done, such as LOD, Cascading Shadowmaps and texture/gltf compression. All but LOD have been implemented.
One that grabbed my attention was Object/Occlusion Culling. The level is flat with several buildings, so this could actually make a big difference.
How does one go about implementing this? Are there any other things I should try to implement?

three does that out of the box without you doing anything.

the bottleneck is vertex count, draw calls and materials. reduce all three. vertex count in blender, draw calls with instancing, and materials with texture atlases.

in the end you will have light models, a few drawcalls, no more than 100, and one single material for everything.

1 Like

Hey! First of all thanks for the reply!
1- How does one go about doing such texture atlases? Is there any guide available?
2- How do I check the amount of drawcalls happening?

three does frustum culling – not occlusion culling unfortunately. Maybe in a WebGPU-powered future version.

I’m hesitant to suggest any particular optimizations without knowing what’s bottlenecking your app now. Do you have numbers like …

  • vertex count
  • draw call count
  • texture count, and resolution
  • how expensive are your materials? e.g. if you swap them all out for MeshBasicMaterial, what happens to frame time? if you turn off lights and shadows?
  • current framerate / ms spent drawing per frame

oh that is my mistake, i misread “occlusion culling”.

1 Like

This webapp runs well on my main PC, which has a 1080ti and a good processor. Problem is on lower end machines, ideally at 1080p
First print has the (geometry count, texture count) and the ms per frame on a laptop with no graphics card (on my main PC its around 13ms). The resolution is whatever resolution the window has, usually its 1080p. On my main PC it is 2K.

When setting the materials to MeshBasicMaterial via scene.overrideMaterial the ms between frames jumps between 50 and 66 ms (from 66 to 100), so the materials are a bit taxing, but 50-60 is still too much.

Finally, the scene’s vertex count sits at 775707. There are times when the scene must all be rendered, so yeah, not great. I used Specter.js (second picture) for the drawcalls and I got around 4200 T-T. I suspect that blender gltf exports to threejs do NOT keep instancing of materials and meshes.

Something to try would be…

npm install --global @gltf-transform/cli

gltf-transform optimize in.glb out.glb

… there are a fair number of options, so try gltf-transform optimize --help to adjust if that doesn’t get what you need. The tool will try to instance anything it can, if Blender did not. In general I wouldn’t count on exports from a DCC tool to be ready for production, you’ll generally need to run some optimization on the models after export for that.


Perfect! Just one question. I assume the tool will try to instance anything within a file, not between files. Since I am trying to implement LOD for further optimization, is there a way to have said instancing take place between files?

Cross-file instancing wouldn’t be something glTF Transform can do to your models, I think it would need to be applied in the loading process. Maybe R3F’s instancing has something like that, or it can be done manually as shown in the instancing + scatter example.

Probably then you’ll want to set the --no-instance flag. This will avoid adding THREE.InstancedMesh, so possible instances remain separate objects, but will still remove any duplicate copies of the same geometry data where possible.

1 Like

This is a bit out there but what if I loaded everything in one file, have it optimized and then separate the meshes on load? That could probably work.

Anyway I will be trying everything! Thanks for the help :smiley:

That’s reasonable too — I think it just depends how you prefer to work. Having InstancedMesh produced directly when loading the file could be useful, or you might prefer the control of setting that up yourself.

1 Like