Hi members.
I’m working on a project that uses CircleGeometry, ShaderMaterial, and SimplexNoise for noise in their animations. Link of a live demo to see the results.
If you open the demo, you can see there is a lack of performance in it.
I saw many examples that using something like my demo in their pages, but way smoother!
Now, I need some performance tips to improve the performance of this project. It’s very critical that the performance should be very good, especially on mobile devices.
Sorry to ask it this way, but I really need some help with this.
I can’t share public code, but if someone needed to see the source, I can give limited access to its repo (:
Thanks.
The first thing I would recommend is the usage of BufferGeometry. So instead of:
this.geometry = new THREE.CircleGeometry(10, 128, 6, 6.3);
use
this.geometry = new THREE.CircleBufferGeometry(10, 128, 6, 6.3);
All instances of THREE.Geometry have to be internally converted to BufferGeometry for rendering. Besides, THREE.Geometry allocates much more memory than BufferGeometry. By simply using CircleBufferGeometry, you avoid all this overhead.
Thanks, @Mugen87.
When I use CircleBufferGeometry , I got some errors for this.mesh.geometry.vertices because I’m using vertices to shape the circle in every render, and it seems with CircleBufferGeometry the vertices are undefined. How can I fix this?
for (let i = 0; i < this.mesh.geometry.vertices.length; i++) {
const bubble = this.mesh.geometry.vertices[i];
bubble.normalize().multiplyScalar(1 + 0.3 * this.simplex.noise4D(bubble.x * spikes, bubble.y * spikes, bubble.z * spikes + time, 3));
}
this.mesh.geometry.computeVertexNormals();
this.mesh.geometry.normalsNeedUpdate = true;
this.mesh.geometry.verticesNeedUpdate = true;
You have to work with BufferAttribute instead. The official examples are full of related code since they were migrated to BufferGeometry since a while now. I’ve not tested this code but it should be:
const positionAttribute = this.mesh.geometry.getAttribute( 'position' );
const vertex = new THREE.Vector3();
for (let i = 0; i < positionAttribute.count; i++) {
vertex.fromBufferAttribute( positionAttribute, i );
vertex.normalize().multiplyScalar(1 + 0.3 * this.simplex.noise4D(bubble.x * spikes, bubble.y * spikes, bubble.z * spikes + time, 3));
positionAttribute.setXYZ( i, vertex.x, vertex.y, vertex,z );
}
positionAttribute.needsUpdate = true;
geometry.computeVertexNormals();
Now I fill its animation is smoother than before. Thank you @Mugen87.
Other than this, when I scroll, the lack is more sensible. I think when I move my objects, it needs more process and calculations.
This is the part of the code that moves the object:
One more tip regarding your geometry: If you are updating the position attribute of your circle geometry per frame, it’s recommended to set a special value for the usage property. In your case, do this when creating the geometry:
Do you think there is a better way for using simplex noises? I use simplex-noise that is a noise lib with js. But I read somewhere that noises can work better if use them in shaders.
It is possible to do this in the shader, yes. It could help to improve the app’s overall performance if it is still CPU bound.
The following article is quite interesting in this context. You might want to check out the presented approaches and see if it helps: https://thebookofshaders.com/11/
The idea is to make a performance analysis e.g. with Chrome dev tools and check for hot spots in your JavaScrip code.
Apart from that you can easily detect GPU bound applications by just shrinking the browser window and thus reducing the resolution. If the performance gets better, there is app is fragment-shader bound (meaning too much work happens in the fragment shader). If the performance gets better by reducing just the vertex count, the application is probably vertex shader bound.