I'm new to Three.js and I ended up with 2 ways of moving the vertices of a plane. I was wondering which one of the two ways should I use in terms of performance or simply in terms of best practices.
In the first function, I update the vertices position with a vertexShader, and the second one I update the position of the vertices by using the bufferGeometry position attribute of the THREE.mesh.
demo: https://olivierlarose.github.io/Threejs-Wave-Animation/
code: https://github.com/olivierlarose/Threejs-Wave-Animation
void main() {
vUv = uv;
float calc = height * sin(position.x * 10.0 + time);
vec3 newPosition = position;
newPosition.z = newPosition.z + calc;
gl_Position = projectionMatrix * modelViewMatrix * vec4( newPosition, 1.0 );
}
animate(){
const time = this.clock.getElapsedTime() * 3;
const position = this.cube.geometry.attributes.position;
for(let i = 0 ; i < position.count ; i++){
const calc = this.height * Math.sin(position.getX(i) * 10 + time);
position.setZ(i, calc);
position.needsUpdate = true;
}
requestAnimationFrame(this.animate.bind(this));
this.renderer.render(this.scene, this.camera);
}
Thank you
If you re-calculate your positions in JavaScript, you'll need to upload these new positions to the GPU on each new frame, which can create a big bottleneck as your vertex count goes higher. Plus, you'll need to perform Math.sin()
once per vertex, which can become costly in a single thread when you have thousands and thousands of vertices.
The best way in terms of performance is to update the positions in the vertex shader. This is because your geometry's position
attribute gets uploaded to the GPU only once. Additionally, you get the boost in performance from calculating sin()
in parallel, which is super fast in the GPU, compared to the CPU.