BatchMesh Memory Issue

So, I have a scene of InstancedMeshes. The user can increase the meshcount to thousands if they want to. I needed to place text on these instances though and so I used a BatchMesh solution. Of course, without the text (MeshBasicMaterial) the model runs great at 60FPS. However, after applying the BatchMesh of text the model begins to chug. My entire model is still at 1 drawCall but with the text its a slug. How do I further optimize the batchmesh to be faster? Ive tried some geometry disposal but Im not sure Im doing it right as it hasn’t produced much success. The main difference I see between the BatchMesh and InstancedMesh solution is indeed the removal of the geometry in the InstancedMesh after the mesh is rendered.

If I recreate the text mesh as InstancedMesh then of course I get a copy of the same text but this text runs extremely fast compared to the BatchMerge. How do I optimize BatchMesh to perform like InstancedMesh?

What is the BatchMesh object you’re referring to?

1 Like

Hi Don, thanks for the reply. Do you mean - am I using mergeBufferGeometry? If so then yes that’s what I’m using. The text is saved as InstancedBuffer to a geometry array and then a matrix4() is added to an object.userData [array] for each piece of text. If you like I can provide an example.

I’m using r128, Btw.

I see, yeah I didn’t know you meant mergeBufferGeometries(...). There are other possible meanings like this BatchedMesh proposal, three-batch-manager, and three-batch-mesh.

My entire model is still at 1 drawCall but with the text its a slug…

Keep in mind that once you merge or instance things, they can no longer be frustum culled individually (i.e. the renderer has to draw them whether they’re in the camera’s view or not). This will be a performance loss if the additional vertex counts drawn are enough to offset the draw call gains.

If you’re looking for fast text rendering, and currently using text geometry, I would perhaps have a look at GitHub - protectwise/troika: A JavaScript framework for interactive 3D and 2D visualizations instead. Alternatively you can merge things into smaller batches that are collocated in 3D space.

Troika Three-TextMesh is interesting. I’ll look at that some more. I guess I’m running into that scenario where too many non-culled vertices are in view. No more possible optimization tricks? How is it that InstancedMesh gets away with it? Is it that it has no vertices?

I guess I’m running into that scenario where too many non-culled vertices are in view.

Yes, but it requires far fewer vertices for each letter than normal text geometry, so you can have a lot more text without reaching this scenario.

Instancing can have the same issue, depending on how many vertices are in the mesh being instanced. Using smaller batches of instances can similarly be useful.

After some tweaking I found that using TextBufferGeometry was a viable solution. Your point of too many vertices was indeed the issue. However, after massaging the text geometry I was able to get a ton of MergedText with low vertices running very smoothly.

Keys were:

1.) Keep the curve segment count as low as possible. For my text a segment of 3 was plenty.

2.) Keep the bevel disabled. The bevel increases vertice count.

3.) Use BasicMaterials.

4.) If you need extrusion depth then set the height parameter as it simply extends geometry depth along existing vertices instead of creating new ones.

For me, the reduced segment and bevel geometry was performant in large numbers but looked a little blocky for my taste. It was still fairly aliased but at different zooms and rotations the mesh would pixelate a little. To overcome a slight anti-aliasing issue I implemented a post processing bloom effect and set a custom shader property for the globalBloom in the fragment shader. This gave me not only a slight (controllable) glow to the text but also did a great job overcoming the reduced text geometry aliasing.

My model is running hundreds of panels of unique labels, SVG Icons and paragraphs of text at 60FPS all day long. Entire model is 100% InstancedGeometry using only 1 single drawCall.

Thank you ThreeJS! I love this API! Beautiful renderer.