1
votes

I load .obj model in Three.js and then create independent meshes from its faces for really interesting animation. But the problem is a very bad performance with so much meshes.

In fact, single mesh with 10000 faces works beautifully. But separated 10000 meshes (created from these faces) work badly - even without animation, just static scene.

How can i optimize performance with saving such animation?

Link: http://intelligence-group.ru/test.html

Here is the code creating meshes:

` obj_loader.load(
        '/assets/models/zeus.obj',
        function(object) {

            var material = new THREE.MeshPhongMaterial( {
                    color: "#eeeeee",
                    shading: THREE.FlatShading,
                    metalness: 0,
                    roughness: 0.5,
                    refractionRatio: 0.25
            } );

            var face = new THREE.Face3( 0, 1, 2 );

            for (var i = 0; i < object.children.length; i++) {
                var child = object.children[i];
                var geometry = new THREE.Geometry().fromBufferGeometry(child.geometry);

                for (var i = 0; i < geometry.faces.length; i++) {
                    var new_geometry = new THREE.Geometry();
                    var a = geometry.faces[i].a;
                    var b = geometry.faces[i].b;
                    var c = geometry.faces[i].c;
                    new_geometry.vertices.push(geometry.vertices[a]);
                    new_geometry.vertices.push(geometry.vertices[b]);
                    new_geometry.vertices.push(geometry.vertices[c]);

                    new_geometry.faces.push( face );
                    new_geometry.computeFaceNormals();

                    var mesh = new THREE.Mesh( new_geometry, material );
                    group.add( mesh );
                }

                full_orig_array(group); //animation function - not the reason of bad optimization!
            }

            scene.add(group);
        }
    );`

Important: after completion of animation i substitute 10 000 meshes with one single mesh (original object from loader) - and then you can see big improvement of performance. It's not about animation - i checked it: even without animation 10 000 meshes have the same bad performance.

As i understand, it's about different geometries in each mesh. But i don't know how to solve this problem(

Please take into account that i don't duplicate geometry - each mesh's geometry is unique. That is the problem!

2

2 Answers

2
votes

There are already a number of answers here on stackoverflow about the performance cost of drawcalls and state-changes so I won't go into that. You NEED to get the number of drawcalls down to render efficiently. How to do that is completely up to your exact problem and your creativity.

My suggestion would be to use a single BufferGeometry: You could just animate all vertex-positions within a single buffer-geometry. You would need to keep the state (translation, rotation, etc) outside of the geometry, but you can write code that freely transforms all of your triangles as if they were single objects.

1
votes

You get overhead from many drawcalls and webgl state change. Rendering as one mesh is a single draw call vs 10.000.

You can use three's InstancedBufferGeometry to merge these into one call, without duplicating the geometry (thus saving both memory and overhead).

This class unfortunately does not work with default materials, shadows etc. It's a fairly low level struct.

I wrote a further abstraction of this that should work on the same level as THREE.Mesh and work with shadows, AO, depth etc.

https://www.npmjs.com/package/three-instanced-mesh