What can cause requestAnimationFrame to drop frames in an efficient webgl loop?
Asked Answered
P

1

7

I have been programming a javascript demo/test to learn WebGL. I have a fairly efficient game loop structure that (according to Chrome Dev Tools) only takes 1-2 milliseconds to run. I am using requestAnimationFrame to schedule the running of the loop (because this is apparently the "proper" way to perform 60fps animation). When I look at the Timeline of constructing the frame, the actual javascript code is minimal, but the 'idle' part of the frame can push the frame well over the 30 fps line. The FPS counter shows 20-40fps with lots of drops (almost like a saw tooth).

Is there anything else I can account for if my rendering loop is already 1-2ms when it has to fit into 16 ms to run 60fps?

If I convert the loop into a setTimeout loop it can hold 60fps easily. I can even render it in Retina Resolution without impacting the 60fps.

e.g.

    // 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
}

I also at some point had the gameLoop running "separately" on a setTimeout while the renderLoop was being called by a requestAnimationFrame. Since they are all on the same thread, this seems a bit dodgey since they could step on each others toes.

Psychomotor answered 24/2, 2014 at 5:15 Comment(2)
Can you post samples?Fey
I generally use the idea on your last paragraph: game logic on a separated setTimeout. It's logically better (requestAnimationFrame "tracks" the redraw event which doesn't have any thing to do with game logic), and I think it's because they're on the same thread (so they won't be executed concurrently) that they won't "step on each others toes".Errand
A
0

requestAnimationFrame implementation varies in different browsers, and it is up to a browser to maintain it's underlying behaviour.

There is no guarantee that it will render 60fps, the only it guarantees that you will get your function executed as close as possible to the moment of rendering (just before swapping buffers to send image data to the screen).

If you use setTimeout you might get more frequent function calls, but that does not gives you 60fps necessary, as screen might refresh still in 30fps, or any other. In that case you are trying to render too often - and that is gpu and energy inefficient (especially on mobile).

Most people couple their update and render logic in single frequency (same function). In any case you need to update your logic (speeds etc.) with delta-time modifier.
That way even with 30fps, speeds of things moving will be same, regardless of fps.

Akeyla answered 3/11, 2014 at 21:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.