Limiting framerate in Three.js to increase performance, requestAnimationFrame?

心已入冬 提交于 2020-08-17 15:57:21

问题


I was thinking that for some projects I do 60fps is not totally needed. I figured I could have more objects and things that ran at 30fps if I could get it to run smoothly at that framerate. I figured if I edited the requestAnimationFrame shim inside of three.js I could limit it to 30 that way. But I was wondering if there was a better way to do this using three.js itself as provided. Also, will this give me the kind of performance increase I am thinking. Will I be able to render twice as many objects at 30fps as I will at 60? I know the difference between running things at 30 and 60, but will I be able to get it to run at a smooth constant 30fps?

I generally use the WebGLRenderer, and fall back to Canvas if needed except for projects that are targeting one specifically, and typically those are webgl shader projects.


回答1:


What about something like this:

function animate() {

    setTimeout( function() {

        requestAnimationFrame( animate );

    }, 1000 / 30 );

    renderer.render();

}



回答2:


The amount of work your CPU and GPU needs to do depend on the workload and they set the upper limit of smooth framerate.

  • GPU works mostly linearly and can always push out the same count of polygons to screen.

  • However, if you have doubled the number of objects CPU must work harder to animate these all objects (matrix transformationsn and such). It depends on your world model and other work Javascript does how much extra overhead is given. Also the conditions like the number of visible objects is important.

For simple models where all polygons are on the screen always then it should pretty much follow the rule "half the framerate, double the objects". For 3D shooter like scenes this is definitely not the case.




回答3:


This approach could also work, using the THREE.Clock to measure the delta.

let clock = new THREE.Clock();
let delta = 0;
// 30 fps
let interval = 1 / 30;

function update() {
  requestAnimationFrame(update);
  delta += clock.getDelta();

   if (delta  > interval) {
       // The draw or time dependent code are here
       render();

       delta = delta % interval;
   }
}



回答4:


I came across this article which gives two ways of solving the custom frame rate issue.

http://codetheory.in/controlling-the-frame-rate-with-requestanimationframe/

I think this way is more robust, as it will have a steady animation speed even on computers that do not render the canvas consistently at 60 fps. Below is an example

var now,delta,then = Date.now();
var interval = 1000/30;

function animate() {
    requestAnimationFrame (animate);
    now = Date.now();
    delta = now - then;
    //update time dependent animations here at 30 fps
    if (delta > interval) {
        sphereMesh.quaternion.multiplyQuaternions(autoRotationQuaternion, sphereMesh.quaternion);
        then = now - (delta % interval);
    }
    render();
}



回答5:


The accepted answer has a problem and gives up to -10fps on slow computers compared to not limiting the fps, so for example without limiting 36pfs, with the accepted solution 26fps (for a 60fps, 1000/60 setTimeout).

Instead you can do this:

var dt=1000/60;
var timeTarget=0;
function render(){
  if(Date.now()>=timeTarget){

    gameLogic();
    renderer.render();

    timeTarget+=dt;
    if(Date.now()>=timeTarget){
      timeTarget=Date.now();
    }
  }
  requestAnimationFrame(render);
}

That way is not going to wait if its already behind.



来源:https://stackoverflow.com/questions/11285065/limiting-framerate-in-three-js-to-increase-performance-requestanimationframe

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!