Ограничение частоты кадров в Three.js для повышения производительности, requestAnimationFrame?

Я думал, что для некоторых проектов я делаю 60 кадров в секунду, это не совсем необходимо. Я решил, что у меня может быть больше объектов и вещей, которые работают со скоростью 30 кадров в секунду, если я смогу заставить его работать плавно при такой частоте кадров. Я решил, что отредактировал прошивку requestAnimationFrame внутри three.js. Я мог бы ограничить ее до 30. Но мне было интересно, есть ли лучший способ сделать это с помощью самого тр .js, как это предусмотрено. Кроме того, это даст мне такое увеличение производительности, о котором я думаю. Смогу ли я сделать вдвое больше объектов со скоростью 30 кадров в секунду, как я буду в 60? Я знаю разницу между запущенными вещами в 30 и 60, но смогу ли я заставить его работать с плавной постоянной 30 кадров в секунду?

Обычно я использую WebGLRenderer и возвращаюсь в Canvas, если это необходимо, за исключением проектов, которые специально нацелены на них, и обычно это проекты webgl shader.

Ответы

Ответ 1

Что-то вроде этого:

function animate() {

    setTimeout( function() {

        requestAnimationFrame( animate );

    }, 1000 / 30 );

    renderer.render();

}

Ответ 2

Объем работы вашего процессора и графического процессора зависит от рабочей нагрузки и устанавливает верхний предел плавной частоты кадров.

  • GPU работает в основном линейно и всегда может вытолкнуть одинаковое количество полигонов на экран.

  • Однако, если вы удвоили количество объектов, то ЦП должен усердно работать, чтобы оживить эти все объекты (преобразования матрицы и т.д.). Это зависит от вашей модели мира и другой работы. Javascript делает сколько дополнительных накладных расходов. Также важны такие условия, как количество видимых объектов.

Для простых моделей, где все полигоны находятся на экране всегда, это должно в значительной степени следовать правилу "половина частоты кадров, удвоить объекты". Для 3D-шутеров, подобных сценам, это определенно не так.

Ответ 3

Я столкнулся с этой статьей, которая дает два способа решения проблемы пользовательской частоты кадров.

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

Я думаю, что этот способ более надежный, поскольку он будет иметь устойчивую скорость анимации даже на компьютерах, которые не отображают холст последовательно со скоростью 60 кадров в секунду. Ниже приведен пример

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

Ответ 4

Этот подход также может работать, используя 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;
   }
}

Ответ 5

Популярный ответ имеет проблему и выдает -10fps на медленных компьютерах по сравнению с не ограничением fps, например, без ограничения 36pfs, с принятым решением 26fps.

Вместо этого вы можете сделать это:

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

Этот путь не будет ждать, если он уже позади.