Как решить разные FPS в requestAnimationFrame на разных браузерах? - PullRequest
9 голосов
/ 07 октября 2011

Как решить различные FPS в requestAnimationFrame в разных браузерах?
Я делаю 3D-игру, используя THREE.js, которая использует requestAnimationFrame, и она быстрая на Google Chrome 15 .
Однако на Firefox 6 он действительно медленный и действительно очень медленный (медленнее, чем Firefox) на IE9 .
Это действительно большая проблемаи мне интересно, есть ли решение для этого.

Спасибо.

Ответы [ 4 ]

14 голосов
/ 17 октября 2011

Обычно нужно создать переменную deltaTime (dt), которая затем будет использоваться в качестве параметра для каждого цикла анимации / обновления.

Код предназначен только для визуализации проблемы / решения.

// ...
timer: function(){
    var now = new Date().getTime(); // get current time
    this.controls.dt = now - this.controls.time; // calculate time since last call
    this.controls.time = now; // update the current application time
    this.controls.frame++; // also we have a new frame
    return this.controls.dt ;
}

для любого вызова функции рендеринга, который вы затем передаете dt

// we call the update function with every request frame
update: function(){
    var dt = this.timer();
    _.each(this.activeViews, function(item){ item.update(dt); });  // this is underscore.js syntax
}

item.update (dt) выглядит так

//...
var x = this.position.get(x);
x = x + (10*dt); // meaning: x increases 10 units every ms.
this.position.x = x;
5 голосов
/ 07 октября 2011

Насколько я знаю, нет способа исправить это, кроме как сделать ваш код менее ресурсоемким.

Chrome, кажется, самый быстрый браузер, но обычно FF не сильно отстает, но IE все еще медленный. В зависимости от методов рендеринга, canvas, svg или webGL, это также очень зависит от вашего локального оборудования, так как для большинства вещей использует клиентскую сторону, а для сложных рендерингов webGL требуется мощный GPU для достижения хороших частот кадров.

Есть способы измерить частоту кадров на лету и соответственно изменить анимацию.
Вот очень простой пример, который измеряет частоту кадров.

function step(timestamp) {
    var time2 = new Date;
    var fps   = 1000 / (time2 - time);
    time = time2;
	
    document.getElementById('test').innerHTML = fps;
    window.requestAnimationFrame(step);
}

var time = new Date(), i = 0;
window.requestAnimationFrame(step);
<div id="test"></div>

Это всего лишь мгновенная мера, которая не настолько точна, вам, вероятно, понадобится что-то, что будет измеряться через некоторое время, чтобы получить более правильную частоту кадров для используемого браузера.

Также обратите внимание на аргумент timestamp, который в requestAnimationFrame представляет собой метку времени с высоким разрешением с минимальной точностью 1 миллисекунды, которая также может использоваться для определения скорости анимации и любой задержки в браузере.

3 голосов
/ 29 декабря 2012

Фреймворк Crafty делает что-то немного другое, но может работать в некоторых случаях - количество игровых тиков за ничью не является постоянным.Скорее, он замечает, когда частота кадров отстает от некоторой идеальной цели, и будет циклически проходить несколько игровых тиков, прежде чем выполнять шаг ничьей.Вы можете видеть пошаговую функцию на github.

Это работает хорошо, пока игра будет работать гладко.Но если вы попробуете что-то более интенсивное использование процессора, это может усугубить ситуацию, так как это будет расставлять приоритеты игровой логики над анимацией.

В любом случае, это будет работать только в том случае, если игровая логика и логика рендеринга несколько отделены.(Если бы они были полностью разъединены, вы могли бы поместить их в совершенно отдельные циклы.)

2 голосов
/ 01 марта 2012

В некоторых браузерах requestAnimationFrame работает примерно так:

setTimeout(callback, 1000 / (16 + N)

, где N - время, необходимое для выполнения вашего кода.Это означает, что он ограничивает ваш FPS на частоте 62 Гц, но если ваш код работает медленно, он будет ограничен чем-то намного ниже.Это в основном пытается сделать разрыв 16 мс между каждым разрывом.Конечно, это не так для всех браузеров и, вероятно, все равно изменится в будущем, но все же может дать вам представление о том, как это работает.

Даже если это было реализовано одинаково в каждом браузере, существует множествофакторы, влияющие на производительность вашего кода и т. д. Вы никогда не можете быть уверены, что ваш код будет работать с постоянной частотой.

...