【问题标题】:How to lock FPS with requestAnimationFrame?如何使用 requestAnimationFrame 锁定 FPS?
【发布时间】:2016-01-13 12:15:22
【问题描述】:

我使用了 Paul Irish 的脚本 https://gist.github.com/paulirish/1579671 在 html 站点内创建动画循环。

虽然它在全屏模式下比在浏览器窗口中更快,但它可以工作。 此外,我观察到不同的速度取决于画布大小和我使用的浏览器。

问题:如何使用脚本确保稳定的帧率?

代码可在此处获得(WebGL 入门,Brian Danchilla 的第 1 章): https://github.com/bdanchilla/beginningwebgl/blob/master/01/2D_movement.html

【问题讨论】:

标签: html webgl frame requestanimationframe rate


【解决方案1】:

为了修饰@emackey 所说的话,

简短的回答是你不能。您可以要求计算机在每一帧中做无限量的工作。我不能保证在有限的时间内完成这项工作。

除此之外,每台计算机都有不同的电量。廉价的集成 GPU 的功率远低于高端显卡。 intel i3 比 i7 慢很多。

您还提到了更改画布大小。绘制 300x150 的画布只需要 45000 像素的工作量。绘制 1920x1080 画布需要 2,073,600 像素或 46 倍以上的工作

您能做的最好的事情就是尽可能减少工作量,或者自动或由用户选择删除慢速硬件上的功能。大多数游戏都是这样做的。它们是图形设置选项,用户可以在其中选择分辨率、纹理分辨率、抗锯齿级别和各种其他内容。

也就是说,您可以尝试进行计算,以便应用中的事物以相对于时间一致的速度移动。在较慢的机器或较大的画布上,帧速率可能会变慢,但每秒移动的距离将保持不变。

您可以使用传递给requestAnimationFrame的时间值来完成此操作

function render(time) {
   // time is time in milliseconds since the page was loaded

   ...do work...

   requestAnimationFrame(render);
}
requestAnimationFrame(render);

例如这里是NON帧率独立动画

function render(time) {

   xPosition = xPosition + velocity;

   ...

   requestAnimationFrame(render);
}
requestAnimationFrame(render);

这是与帧率无关的动画

var then = 0;
function render(time) {
   var timeInSeconds = time * 0.001;
   var deltaTimeInSeconds = timeInSeconds - then;
   then = timeInSeconds;

   xPosition = xPosition + velocityInUnitsPerSecond * deltaTimeInSeconds;

   ...

   requestAnimationFrame(render);
}
requestAnimationFrame(render);

注意:传入 requestAnimationFrame 的时间比Date.now()的分辨率高

Here's an article on it with animations

【讨论】:

    【解决方案2】:

    这样的事情应该可以工作。如果两帧之间的时间差小于您的 FPS 限制,则更新函数将返回并等待下一帧。但这只会限制更新发生得太快;就像 emackey 说的那样,更新循环总是有可能运行得更慢。

    var updateId,
        previousDelta = 0,
        fpsLimit = 30;
    
    function update(currentDelta) {
        updateId = requestAnimationFrame(update);
    
        var delta = currentDelta - previousDelta;
    
        if (fpsLimit && delta < 1000 / fpsLimit) {
            return;
        }
    
        /* your code here */
    
        previousDelta = currentDelta;
    }
    

    【讨论】:

    • 如果你把(1000 / fpsLimit) - tolerance设置成0.1或0.01这样的小值,帧率会更稳定。
    【解决方案3】:

    您无法直接强制执行稳定的帧速率。您的页面不是在用户平台上运行的唯一应用程序,平台功能差异很大。 requestAnimationFrame 尽可能快地运行,不会超过目标设备上的显示更新间隔,但可能会慢得多,具体取决于可用的 CPU、GPU、内存和其他限制。

    这里的标准做法是测量自上一个动画帧以来经过的时间量,通常使用Date.now(),并且每一帧都会将动画推进该时间量。对人眼来说,这使得生成的动画以一致的速度运行,即使帧速率变化很大。

    例如,ShadertoyGLSL Sandbox 等网站运行全屏 GLSL 着色器并传入一个名为 time(或 iGlobalTime)的制服,这是一个 float,表示经过的秒数自从着色器开始。这个时间值会根据每个动画帧渲染的时间不规则地增加,但结果是浮点数似乎以稳定的每秒 1.0 的速度向上计数。这样,基于这个时间值的shader播放就可以显得一致了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-11-14
      • 2012-08-09
      • 1970-01-01
      • 2016-10-26
      • 2018-05-26
      • 2011-08-02
      • 1970-01-01
      • 2013-02-12
      相关资源
      最近更新 更多