2011-10-06 1 views
9

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

Спасибо.

+1

Способ решить этот вопрос - сделать любой код, который вы используете, от быстрого выполнения обратного вызова. Как это сделать нельзя сказать, не видя кода ... –

ответ

5

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

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

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

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

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

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

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

+2

IE9 + на самом деле довольно быстро. Иногда быстрее, чем FF, по моему опыту. – kangax

14

Общей задачей является создание переменной 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 ; 
} 

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

// 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 (дт) выглядит, что

//... 
var x = this.position.get(x); 
x = x + (10*dt); // meaning: x increases 10 units every ms. 
this.position.x = x; 
2

О некоторых браузерах requestAnimationFrame работает что-то вроде

setTimeout(callback, 1000/(16 + N)

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

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

3

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

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

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

Смежные вопросы