【问题标题】:What can cause requestAnimationFrame to drop frames in an efficient webgl loop?什么会导致 requestAnimationFrame 在有效的 webgl 循环中丢帧?
【发布时间】:2014-03-25 14:56:24
【问题描述】:

我一直在编写一个 JavaScript 演示/测试来学习 WebGL。我有一个相当有效的游戏循环结构(根据 Chrome 开发工具)只需要 1-2 毫秒即可运行。我正在使用 requestAnimationFrame 来安排循环的运行(因为这显然是执行 60fps 动画的“正确”方式)。当我查看构建框架的时间轴时,实际的 javascript 代码很少,但框架的“空闲”部分可以将框架推到 30 fps 线以上。 FPS 计数器显示 20-40fps 有很多滴(几乎像锯齿)。

如果我的渲染循环已经是 1-2 毫秒,而它必须适应 16 毫秒以运行 60 fps,我还有什么可以解释的吗?

如果我将循环转换为 setTimeout 循环,它可以轻松保持 60fps。我什至可以在不影响 60fps 的情况下以 Retina 分辨率渲染它。

例如

    // Timeout version
    function gameLoop()
{
setTimeout(gameLoop, 1000/60);
//Process movement, AI, game logic
 renderLoop();
}
function renderLoop()
{
//Drawing all of the 3d stuff
}

v.s.

function gameLoop()
{
requestAnimationFrame(gameLoop);
//Process movement, AI, game logic
renderLoop()
}
Function renderLoop()
{
//draw objects
}

我也曾在某个时候让 gameLoop 在 setTimeout 上“单独”运行,而 renderLoop 被 requestAnimationFrame 调用。由于他们都在同一个线程上,这似乎有点狡猾,因为他们可能会踩到对方的脚趾。

【问题讨论】:

  • 你可以发布样品吗?
  • 我通常使用你最后一段的想法:游戏逻辑在一个单独的setTimeout 上。它在逻辑上更好(requestAnimationFrame“跟踪”与游戏逻辑没有任何关系的重绘事件),我认为这是因为它们在同一个线程上(所以它们不会同时执行)他们不会“互相踩脚”。

标签: javascript google-chrome webgl requestanimationframe


【解决方案1】:

requestAnimationFrame 的实现在不同的浏览器中有所不同,由浏览器来维护其底层行为。

不能保证它会以 60fps 渲染,唯一可以保证您的函数会在尽可能接近渲染的时刻执行(就在交换缓冲区以将图像数据发送到屏幕之前)。

如果您使用 setTimeout,您可能会得到更频繁的函数调用,但这并不需要 60fps,因为屏幕可能仍以 30fps 或其他速度刷新。在这种情况下,您尝试渲染的频率太高 - 这会导致 gpu 和能源效率低下(尤其是在移动设备上)。

大多数人将他们的更新和渲染逻辑耦合在单一频率(相同的功能)。在任何情况下,您都需要使用 delta-time 修饰符更新您的逻辑(速度等)。
这样即使是 30 fps,无论 fps 多少,物体移动的速度都是一样的。

【讨论】:

    猜你喜欢
    • 2016-07-27
    • 1970-01-01
    • 2014-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-30
    相关资源
    最近更新 更多