Performance issues when rendering first frame of ThreeJS app - performance

I currently have a big impact on the performances of my ThreeJS app when I render the very first frame. It causes the Edge and IE 11 browsers to freeze for 5 seconds with a pop-up indicating "This window does not respond", which may scare my users.
Using the Performance profiler of Chrome, it seems the problem come from several ThreeJS functions you can clearly identify in the screenshot below.
WebGLUniforms.upload : 425ms (50.7% frame rendering time)
WebGLProgram.constructor : 327ms (38.9% frame rendering time)
How can I minimize the duration of the functions call ?
Can I create the program over multiple frames? Or upload the uniforms?
Does the number of materials on my 3D models impact these functions ?
I've tried to hide all the models in the scene and show them one at a time, it seems to prevent the freeze, but each model takes 500ms to show, which is not perfect for user experience. Maybe, it's the only way to go.
Thanks for your time
EDIT : The number of materials or their nature (WebGLStandardMaterial?) seems to affect the performances

Put add a few objects to the scene per frame over time. Three.js inits WebGL resources on first use so if there's 100 objects on your scene all 100 objects get initialized the first time you call renderer.render.
So, just put N objects to the scene, call renderer.render, then next frame add N more to the scene, etc until all the objects have been added.
It's probably most important to do it by material and geometry. In other words if you have 10 different materials and 10 different geometries and you're rendering 100 different models (a model takes one material and one geometry), then you want to make sure the first N models you add don't use all the materials and all the models because those are the things that need to get initialized.
Post processing passes also need initialization so if you're using any of those maybe the first frame just init those, then start adding objects.

Related

Large lagging on mouse movement with SketchUp Dae model

I’ve designed a 3D model in SketchUp and I didn’t use any texture. I’m faced with an issue related with lagging on mouse move and rotate process. When I exported the model by Dae format and imported to the three js online editor (three js online editor) mouse movement is being very slow. I think it occurs fps drop. I couldn’t understand what’s problem with my model that I designed. I need your suggestions and ideas how to resolve this issue. Thanks for your support. I’ve uploaded 3D model’s image. Please take a look.
Object Count: 98.349, Vertices: 2,107.656, Triangles: 702.552
Object Count: 98.349,
The object count results in an equal number draw calls. Such a high value will degrade the performance no matter how complex the respective geometry eventually is.
I suggest you redesign the model and ensure to merge individual objects as much as possible. Also try to lower the number of vertices and faces.
Keep in mind that three.js does not automatically merge or batch render items. So it's your responsibility to optimize assets for rendering. It's best to do this right when designing the model. Or in code via methods like BufferGeometryUtils.mergeBufferGeometries() or via instanced rendering.

How to get (console.log) draw calls in interleaved buffer and InstanceMesh threejs

I'm a beginner to threejs. As I'm working in performance optimization of instances I'm working on two different samples of InterleavedBuffer and InstanceMesh.
I want to compare the draw call between both Interleavedbuffer and InstanceMesh to find the difference of how optimized it is. How to get the draw call count between them?
WebGLRenderer has a property call info which contains a series of statistical information about the graphics card memory and the rendering process. It also reports the amount of draw calls per frame like so:
console.log( renderer.info.render.calls );

GLTF anim and morph playback issue when using three.js with more than one mixer

I have a single gltf file, exported from Blender with 6 anims and 20 morph targets. When that's the only skinned gltf object in the scene, everything plays nicely - I can switch between bone anims (run, walk, idle, etc), and get all morph anims (for facial expressions) cycling on a timer, or triggered by events. Yay.
The problem is when I introduce a second skinned object, such as an NPC. At that point lots of weirdness starts to happen.
For example, when morph targets cycle expressions on/off the player object, the NPC model standing nearby scales down and disappears on the off cycle, then scales back up during the on cycle. Another example, at init time the NPC object might randomly turn into an instance of another loaded object (a tree or a building), or occasionally a mini version of some random object, at 10% normal scale, and then start rapidly bouncing around in unpredictable and inconsistent ways. I have no idea what's going on.
I thought it might have something to do with loading multiple mixers, but then that's what the docs state should be done - "When multiple objects in the scene are animated independently, one AnimationMixer may be used for each object." Unless I'm reading that wrong?
I'm using:
npcMixer = new THREE.AnimationMixer(npc);
virtually the same as what I do for the player:
playerMixer = new THREE.AnimationMixer(player);
Is this a bad/mistaken approach?
Perhaps worth noting: I had FBX versions of the player and NPC working just fine together when exported and accessed as individual files. Then I spent a lot of time converting to GLTF since it's faster and lets me wrap all the actions up in a single file, which the FBX exporter does not seem to support (If I'm wrong about FBX being able to export multiple actions in a single file for playback in the three.js context please let me know!).
Three.js r98
Blender 2.79
Thanks for any advice.

Which is the best way to render large number of geometries in three js?

Initially when I start my three.js based application there are very few cubes (less than 50) and they are rendered withing no time. But as number of cubes increase the rendering time increases.
When I reach 150 cubes with each having texture on all six sides.
It takes long time (3 to 5 minutes) to render the scene.
Once the scene is rendered I want to add/remove individual cubes, without rendering the whole scene again.
I have gone through similar question here.
But using this technique has following disadvantage:
It won’t be possible to move the merged objects independently from each other. Or you can no more remove or add a object without recomputing the whole geometry.
How do I solve this issue ?
Note : I am using WebGL Renderer
This seems to work well, no?
http://threejs.org/examples/webgl_interactive_draggablecubes.html
Code seemed sane too, has the cubes as separate objects. Though perhaps you mean that need more..
I edited the example to do 1000 cubes for me now, am getting 40fps on this laptop with intel hd 4000 -- not bad I'd say!

How to reduce Drawcalls for animated GameObjects?

I have a scenario such that I have a wall and whenever player hits the walls it falls into pieces .Each of the piece is the Child GO of that wall.Each of the piece is using same material .So I tried Dynamic Batching on that but it didn't reduce the draw calls.
Then I tried CombineChildren.cs it worked and combined all meshes thus reducing the drawcalls but whenever my player hit the wall it didn't played the animation.
I cannot try SkinnedMeshCombiner.cs from this wiki with the answer from this link check this
beacause my game objects have Mesh renders rather than Skinned Mesh renderer
Is there any other solution I can do for that?
So I tried Dynamic Batching on that but it didn't reduce the draw
calls.
Dynamic batching is almost the only way to go if you want to reduce draw calls for moving object (unless you try to implement something similar on your own).
However it has some limitations as explained in the doc.
Particularly:
limits on vertex numbers for objects to be batched
all must share the same material (not different instances of the same material - be sure to check this)
no lightmapped objects
no multipass shaders
Be sure all limitations listed in the doc are met, then dynamic batching should work.
Then I tried CombineChildren.cs it worked and combined all meshes thus
reducing the drawcalls but whenever my player hit the wall it didn't
played the animation.
That's because after been combined, all GameObjects are combined into an unique one. You can't move them indipendently no more.

Resources