requestAnimationFrame

Most WebGL demos out there (including my WebGL tutorials), use the JavaScript setInterval function to schedule a function to draw the 3D scene so that it is called on a regular basis. This works well enough for simple demos, but has problems if generally used. If a page is loaded in your browser, even if it’s in a hidden tab or window, setInterval keeps getting called. This means that having more than one or two WebGL pages loaded can make your machine bog down.

Luckily, the browser writers are well aware of this problem, and now WebKit (that is, Safari and Chrome) and Minefield both support a new function, officially called requestAnimationFrame (it has slightly different names in different browsers right now, more on that later). This takes one parameter, a function which will be called when the browser thinks you should render your scene again. To use it, you just make your rendering function (tick in most of my tutorials) finish with a call to requestAnimationFrame to ask for itself to be called again next time a frame is needed, and then replace the call to setInterval with an initial call to your rendering function to draw the first frame and schedule a callback for the next.

A few weeks ago, Gman suggested that I switch the tutorials over to using this pattern, which I’m in the process of doing. But in the meantime, I really recommend this article on how to use it (for animation in general, not just WebGL) from Paul Irish. You might also find this utility module from Google useful; among other things, right at the end of the file, it exposes the function in a cross-browser way, so that you don’t need to worry about the naming differences between Mozilla and WebKit.

It’s also worth noting that Mr Doob (of three.js fame) has been recommending that people switch to the new way of scheduling renders, so presumably three.js will switch soon (if it hasn’t already).

You can leave a response, or trackback from your own site.

8 Responses to “requestAnimationFrame”

  1. WebGLU has used requestAnimationFrame for a couple months now.

  2. Shy says:

    If you’re using any kind of wrapper that defaults to setTimeout then you should really put the call at the beginning of tick() and not at the end. If you put it in the end then the next interval you get depends on how long it took you to render the current frame. with the native requestAnimationFrame() this shouldn’t matter but with defaulting to setTimeout() which just measures time it does. The framerate you’ll end up getting will not be constant. The current version of chrome (9.0.x.x) still does not support the native requestAnimationFrame() AFAIK.

  3. Shy says:

    here’s the thread about it from the public mailing list – http://www.khronos.org/webgl/public-mailing-list/archives/1102/msg00079.html

  4. Bo says:

    I’ve played around with this new functionality, and it seems that the animation resulted using requestAnimationFrame is somehow not smooth. The FPS is fine at 60, it’s just the sampling interval that is not as regular as the setInterval(…) method. The result is very slight jump/stutter in animation giving a sense of not smooth / uncomfortable. I don’t know, maybe it’s just because the implementation hasn’t matured. I’m testing using Google Chrome 11 dev builds.

  5. Bo says:

    There is an alternative way to achieve less CPU/GPU usage: Hook up window.onfocus and window.onblur event and set/reset timer to a lower value if the window is out of focus. I’ve reverted the requestAnimationFrame calll and done this in Planet Buster, when out of focus it drops to 30 FPS, when in focus it restore to 60 FPS. Happy days.

  6. giles says:

    @Shy — thanks, that’s a great point. The only concern I’d have with putting the requestAnimationFrame call at the start of the rendering function would be that long renders might make it trigger before the render is complete — but I guess JS’s single-threaded nature makes this a non-issue.

    @Bo — interesting, I’ve found quite the opposite: requestAnimationFrame looks much smoother. That might be because I’ve switched over from Sylvester to glmatrix at the same time, though.

    Either way, if requestAnimationFrame is what the browser makers recommend, it’s probably what I should be using in the tutorials — even if it causes short-term glitchiness. (Hey, if all of the demos that do what the browser makers recommend suddenly look crappy, that should give them an incentive to fix the implementation ;-)

  7. victor says:

    does WebGL API offers some native support to work with animation?

Leave a Reply

Subscribe to RSS Feed Follow Learning WebGL on Twitter