Sprite vs Mesh for orthographic camera and without lighting

For my project I only use an orthographic camera. The scene is basically a grid with a lot of images, icons, text and other 2D things. Sometimes I animate the rotation or movement of an image (with react-spring/tree).

I used to draw a lot of icons with font awesome and troika-three-text, but I’ve had performance problems. In search for a solution, I stumbled over sprites and tested them as a replacement with a canvas texture and it is working a lot better.

Now my question: As far as I undertand, a sprite is always facing the camera. What will be more performant? Using sprites or meshes? Since most images are different, I cannot use instancing as a performance measure. Are sprites inherently more performant? And as a follow-up question? Can I also animate the sprites? While I animate the current meshes, they always face the camera.

1 Like

Sprites aren’t inherently more performant than a quad rendered with a “face the camera” shader.. but they have a lot of little built in features that can make them more useful out of the box.

r.e. Instancing with different images, have you looked into using a “texture atlas” for rendering? If you’re already somewhat proficient with shaders, it can be a huge performance win, especially if you have large amounts of sprites.

Yes, you can animate sprites. See this example.

Instancing with 3d textures (layer).

Thanks for your suggestions. I’ve come to the realisation that sprites cannot be instanced. To keep draw calls low, I’m using meshes.

But instancing opens a whole new can of worms.

The suns are the instanced meshes with MeshBasicMaterial, while the question mark is a normal mesh.

The top sun should be displayed above the question mark and the bottom sun under the question mark. All of these meshes are using a square plane geometry. As you can see, the top sun is removing a chunk of the question mark.

If I set drawDepth to false, the top sun is rendered under the question mark, so that is not an option. Does someone has a solution for the problem? Is it possible at all, since the instanced meshes are rendered at the same time?

Add sprites in instancing like layer. First add “Sun” then “Question”.

mesh["instancing"].setMatrixAt(0,mesh["sun_1"].matrixWorld);
mesh["instancing"].setMatrixAt(1,mesh["sun_2"].matrixWorld);
mesh["instancing"].setMatrixAt(2,mesh["question"].matrixWorld);

The problem is that questionMark is not part of the instance and I cannot easily add it to the instance. The question mark is just a representation for an arbitary mesh. It could also be a mesh with a shapeGeometry or a text or something totally different.

The first solution is to change position.z.

mesh["sun"].position.z=0;
mesh["question"].position.z=1;

The second solution, but may reduce performance slightly:

renderer.autoClear=false;
renderer.clear();
renderer.render(mesh["sun"],camera);
renderer.clearDepth();
renderer.render(mesh["question"],camera);

Both solution are rendering both suns behind the questionMark, but I want the top sun before the questionMark and the bottom sun behind the questionMark.

I think I just have to accept that it is not possible what I want to achieve

mesh["sun_1"].position.z=0;
mesh["question"].position.z=1;
mesh["sun_2"].position.z=2;

or

renderer.autoClear=false;
renderer.clear();
renderer.render(mesh["sun_1"],camera);
renderer.clearDepth();
renderer.render(mesh["question"],camera);
renderer.clearDepth();
renderer.render(mesh["sun_2"],camera);

While this works (and I had it before like this), this does not use instancing. So I again have a draw call for every sun.

I’ve got a lot of suns on the same z-position and my next approach will be to only add them to the instancedMesh and the other ones will be just normal meshes. It is not as good as I would liked it, but it will have to do.

Depend of how much “Questions” will be and in which layer they must be. If 1 “Question@” then 3 draw calls.
First instancing with sun and other stuffs sorted like layer and position 0
Second is “Questions” with position 1. Third instancing with sun and other stuffs sorted like layer and position 2.

If you want to render them all with a single drawcall, you can use onBeforeCompile to modify the shader to pull texture data from different regions of a texture atlas (a single large texture with all your images in it) … based on another data attribute you add to the instancemesh, or you can hijack the color attribute and use that to store your desired texture uv rectangle…
then add them to the instance list in the order you want them layered, with depthWrite = false.

1 Like