How to create lots of optimized 2D text labels

I have a Label class that gets created 300 times via CSS2D that can be moved and changed. Issue is, becomes laggy fast. Is there a more properly optimized way of creating many dynamic 2D texts? ( They need to be all potentially visible simultaneously )

class Label {
	constructor( text, position ) {
		this.div = document.createElement( 'span' );
	    this.div.className = 'label';
	    this.div.textContent = text;
	    this.div.style.color = 'white';
	    this.div.style.backgroundColor = 'transparent';
	    this.object = new CSS2DObject( this.div );
	    this.object.layers.set( 0 );
	    this.object.castShadow = true;
	    this.object.position.set( position.x, position.y + 0.5, position.z );
    }

    UpdateText( text ) {
	    this.div.textContent = text;
    }

    UpdatePosition( position ) {
	    this.object.position.set( position.x, position.y, position.z );
    }
}

I tried using troika, but it added +300 draw calls to my scene :confused:

Example of label type needed

Instancing + Texture atlas, maybe :thinking: Letterfall [on terrain]
also, recalled about this one: https://codepen.io/prisoner849/full/PoxbYZZ

2 Likes

divs/css would be bad for performance. distinct troika labels would most likely also be slow.

there are only few things capable of doing what you need out of the box, but the caveat is that large scale apps which would require such things aren’t typically made in vanilla, so these solution have a different focus:

both can display hundreds of thousands of labels/annotations. if it’s an option i would prefer uikit nowadays out of the two because you would be able to style the annotations. uikit can, with some limitations, also be used in vanilla. otherwise texture atlasing is perhaps what you want, but keep in mind that fonts will pixelate if you zoom in, it won’t be as crisp as troika/sdf.

1 Like

https://codepen.io/prisoner849/full/PoxbYZZ

This is close to what I need, but it seems this is great only if the text doesn’t need to be dynamically changed (the labels are used for player’s names in a game). Also the white background would need to be transparent

I’m not familiar with react, I will give it a try if I can’t find any other solution close to my understanding

Tried integrating the Instancing + Texture atlas from your code - to my surprise, performance took an even bigger nose-dive, especially when updating the CanvasTexture dynamically ( a single rewrite halves my fps for a second). I think the transparency may be the main culprit…

I think I may have to find a different method altogether such as hiding some labels when there are too many to display