html 限制Three.js中的帧速率以提高性能,requestAnimationFrame?

sy5wg1nm  于 2022-11-27  发布在  其他
关注(0)|答案(6)|浏览(201)

我在想,对于一些项目来说,我并不完全需要60fps。我想如果我能让它在30fps下流畅地运行,我可以有更多的对象和东西在30fps下运行。我想如果我在three.js中编辑requestAnimationFrame填充,我可以这样将它限制在30。但是我想知道是否有一个更好的方法来使用提供的three.js本身来做到这一点。另外,这会给我带来我所想的那种性能提升吗?我能以30fps渲染两倍于60 fps的对象吗?我知道以30 fps和60 fps运行东西的区别,但我能让它以30fps的恒定速度平稳运行吗?
我通常使用WebGLRenderer,如果需要的话,可以回退到Canvas,除非是专门针对一个项目的项目,通常是webgl着色器项目。

0s0u357o

0s0u357o1#

这样的事情怎么样:

function animate() {

    setTimeout( function() {

        requestAnimationFrame( animate );

    }, 1000 / 30 );

    renderer.render();

}
xqnpmsa8

xqnpmsa82#

这种方法也可以工作,使用THREE.Clock来测量增量。

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;
   }
}
csbfibhn

csbfibhn3#

CPU和GPU需要完成的工作量取决于工作负载,它们设置了平滑帧速率的上限。

  • GPU主要是线性工作的,并且总是可以向屏幕推出相同数量的多边形。
  • 然而,如果你把对象的数量增加了一倍,CPU就必须更加努力地工作来使这些对象(矩阵变换等)动画化。这取决于你的世界模型和Javascript所做的其他工作,额外的开销有多大。同样,像 * 可见 * 对象的数量这样的条件也很重要。

对于简单的模型,所有的多边形都在屏幕上,那么它应该几乎遵循“一半的帧率,双倍的对象”的规则。对于3D射击像场景,这绝对不是这样的。

wtlkbnrh

wtlkbnrh4#

我遇到了这篇文章,它给出了两种解决自定义帧速率问题的方法。
http://codetheory.in/controlling-the-frame-rate-with-requestanimationframe/
我认为这种方法更健壮,因为它将有一个稳定的动画速度,即使在计算机上渲染画布不一致的60 fps。

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();
}
olqngx59

olqngx595#

接受的答案有一个问题,并放弃了高达-10fps在缓慢的计算机相比,不限制fps,所以例如,没有限制36 pfs,与接受的解决方案26 fps(对于60 fps,1000/60 setTimeout).
您可以执行以下操作:

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);
}

如果已经落后了,那条路是不会等的。

wfypjpf4

wfypjpf46#

前面的答案似乎忽略了requestAnimationFrame的设计意图,并因此进行了一些无关的调用。requestAnimationFrame接受一个回调,而回调又接受一个高精度的时间戳作为其参数。因此,您知道当前时间,并且不需要调用Date.now()或任何其他变体,因为您已经知道了时间。所需要的只是基本的算术:

var frameLengthMS = 1000/60;//60 fps
var previousTime = 0;

function render(timestamp){
  if(timestamp - previousTime > frameLengthMS){
   /* your rendering logic goes here */
       drawSomething();
   /* * * * */
    previousTime = timestamp;
  }
  requestAnimationFrame(render);
}

相关问题