How to batch different meshes with same materials into one draw call?

What’s the best way to batch several meshes that share the same material into one draw call?

For example, a set of 100 meshes where each mesh geometry has different verts/faces from the other mesh geometries, changes transformation each frame, but shares all the same materials across the meshes? Looking to ideally draw all these meshes in a single draw call.

Specifically looking for a solution outside of mergeGeometries which doesn’t (or doesn’t seem to) be applicable to meshes whose transformations constantly change.

Since the geometries of your meshes are different, you can use instanced rendering. And since you don’t want to use BufferGeometryUtils.mergeBufferGeometries(), there is no other option left.

Engines that support auto-batching do actually the same. Even when the transformation changes per frame, the geometries are merged into a single buffer. Since three.js does not perform this automatically, you have to do this on application level if required.

3 Likes

You can use all in one geometry by merging all shapes once and giving the vertices IDs with an buffer attribute to identify each individual shape and store the matrices in a texture instead InstancedBufferAttribute. You can fetch the corresponding matrix from it then.

1 Like

Researching in more I did end up going with mergeGeometries but also assigning each pre-merged geometry its own “group” id, then when rendering passed in an array of uniforms to represent each transformation. This does get limited by the number of uniform values I can pass in, but is ok so long as I stay below 1024/6 (pos+rotation) = ~170 meshes.

Re : @Fyrestar how would I store the matrices in a texture? Wouldn’t this lose precision pretty quick?

Not as float texture.

2 Likes

I’d never even heard of floating point textures before! Very cool; can totally see how this could be better utilized.

This got merged few hours ago https://github.com/mrdoob/three.js/pull/25059

3 Likes