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

如果我的渲染循环已经必须是16毫秒才能运行60fps,那么我还能解释什么吗?

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

例如

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


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

我还曾在某个时间让gameLoop在setTimeout上“单独”运行,而requestAnimationFrame调用了renderLoop。由于它们都在同一线程上,因此似乎有点躲闪,因为它们可以互相踩脚趾。

最佳答案

requestAnimationFrame的实现在不同的浏览器中会有所不同,并且取决于浏览器是否维护其基本行为。

无法保证它将以60fps的速度进行渲染,仅保证可以在渲染时(在交换缓冲区以将图像数据发送到屏幕之前)使函数尽可能地接近渲染时执行。

如果使用setTimeout,则可能会更频繁地调用函数,但这并没有给您60fps的必要条件,因为屏幕可能仍以30fps或任何其他速度刷新。在这种情况下,您将尝试过于频繁地进行渲染-这就是GPU和能源效率低下的问题(尤其是在移动设备上)。

大多数人将更新和渲染逻辑耦合到单一频率(功能相同)。无论如何,您都需要使用delta-time修饰符更新逻辑(速度等)。
这样,即使采用30fps,无论fps如何,事物移动的速度都将相同。

07-24 16:49