I have coded my first threejs project (AmbientLight, DirectionalLight, PerspectiveCamera, OrbitControls, WebGLRenderer) for the following use case:
I have a scene where I created 1800 BufferGeometry objects based on a list of vertices.
On top of that I created 1800 TextGeometries each being positioned in the center of its related BufferGeometry each with a text based on the related BufferGeometry’s “userData”.
Furthermore I have some user interactivity in a way that you can hover with the mouse over the objects using Raycaster to have them change their color as a feedback and display their individual “userData” in an HTML table.
As you might guess I now face some nasty performance issues with an fps<15.
I tried to research for performance optimization techniques like merging the meshes and re-using materials etc. But as far as I understand I would lose the ability of interacting with the individual objects, wouldn’t I?
What can I do to improve the performance without losing the ability to interact with the individual objects?
I suppose you mean InstancedMesh? I have looked into that shortly during my research but then I was put off, because it says that “if you have to render a large number of objects with the same geometry”. In my case the BufferGeometries are built based on a list of vertices, so that each geometry might be a little different in terms of shape.
Or do I misunderstand the statement? Is it still possible to use InstancedMesh in my case?
I will need to take some time to look at the code to understand if it’s working out for me…
I found out that in my case the 1800 BufferGeometries are not really a problem, they still allow an fps=56 which is fine I guess. But rather the 1800 TextGeometries seem to be eating the performance! So I tried to implement instancing for the meshes of the TextGeometries only.
It basically works, but unfortunately I have not yet found a way to change the individual text to be displayed. I know how to set the individual position (matrix.setPosition) and orientation (matrix.lookAt) of the instanced meshes, but how can I change the text?
I have a structure of many quad and tria meshes (created from vertices via json)
I want to load text data (via json) that contains a dict of data for each quad/tria
I want to map the different sets of text data to the quad/tria meshes from the loaded dict based on a selection from a pull down menu
I want some mouse hover interactivity like displaying the complete list of text data per quad/tria mesh in a html table together with a color change “feedback” when the mouse hovers over the quads/trias.
I managed to achieve all requirements, but only with TextGeometries, which is not really fun due to the low fps.
I tried different approaches:
Text Textures: not possible, because I cannot have text images for all possible text.
CanvasGeometry: flexible with text, but the quality is not great due to the blurriness if scaled
TextGeometry: flexible with text, good quality if scaled, but resource intensive due to triangulation
Does anyone know a better approach to my use case that I overlooked?
Honestly, most available ways of rendering text are going to handle this poorly out of the box… SDF fonts would be my recommendation, since it should be possible to merge their geometries or use instancing. I’d try Troika 3D Text - Troika JS, and ask on their github page if the performance is still bad. It supports GPU instancing but that part is currently undocumented (GPU Instancing - Troika JS).
three-bmfont-text might also be an option if you merge the geometries after generating.
I wouldn’t try to raycast against the text directly, it’d be much better to just raycast against simple planes.
I guess these are sprites if I’m not wrong. In my very case I would like to have the text really “mapped” to the planes, so sprites are not exactly for that, since they keep their position and are always in front.
I hope I don’t mix up, at least that’s what I understood about sprites…