Modern browsers luckily have a solution for that with the requestAnimationFrame function. With requestAnimationFrame, you can specify a function that is called at an interval. You, however, don't define this interval. This interval is defined by the browser. You do any drawing you need to do in the supplied function, and the browser will make sure it is painted as smoothly and efficiently as possible. Using this is really simple (the complete source can be found in the 04-04.js file); you just create a function that handles the rendering:
function renderScene() {
requestAnimationFrame(renderScene);
renderer.render(scene, camera);
}
In this renderScene function, we call requestAnimationFrame again, to keep the animation going. The only thing we need to change in the code is that instead of calling renderer.render after we've created the complete scene, we call the renderScene function once to initiate the animation:
...
document.getElementById("webgl-output")
.appendChild(renderer.domElement);
renderScene();
If you run this, you won't see any changes yet compared to the previous example because we haven't animated anything yet. Before we add the animation, though, we introduce a small helper library that gives us information about the frame rate the animation is running at. This library, from the same author as Three.js, renders a small graph that shows us information about the rate at which the scene is rendered.
To add these statistics, we first need to include the library in the <head> element of the HTML, as follows:
<script type="text/javascript" src="../../libs/util/Stats.js"></script>
The only thing left to do is initialize the statistics and add them to the page:
function initStats(type) {
var panelType = (typeof type !== 'undefined' && type) && (!isNaN(type)) ? parseInt(type) : 0;
var stats = new Stats();
stats.showPanel(panelType); // 0: fps, 1: ms, 2: mb, 3+: custom
document.body.appendChild(stats.dom);
return stats;
}
This function initializes the statistics and, based on the passed in type variable renders the frames per second, the time it took to render the frame, or the amount of allocated memory. At the beginning of our init() function, we'll call this function, and we've got stats enabled, as follows:
function init(){
var stats = initStats();
...
}
Since this is something we want to add to each example, we don't add the initStats function to the sources of our examples, but this function, together with other useful helper functions, are added to the util.js file.
This file is included in the header of the HTML pages as follows:
<script type="text/javascript" src="../js/util.js"></script>
The only thing left to do now is to tell the stats object when we're in a new rendering cycle. We do this by adding a call to the stats.update function in our renderScene function, as follows:
function renderScene() {
stats.update();
...
requestAnimationFrame(renderScene);
renderer.render(scene, camera);
}
If you run the code with these additions, you'll see the statistics in the upper left-hand corner, as shown in the following screenshot:
60 FPS (49-60)