Extended Functionality
Several APIs required for modern games became available for developers under the umbrella of HTML5. Not all of them are actually part of the HTML5 standard but the term is often used to refer to all of them. Not all browsers support all of the APIs, in some cases making it impossible to execute a game that has certain quality requirements. For example, if your game requires advanced 3D graphics then you will require support for the WebGL API.
Due to the diversity of the browsers and the reluctance of some browser vendors to support specific APIs, all the browsers lack at least one or two APIs. Many developers will have to fallback on alternative solutions to achieve the required quality. The only fallback option that provides for all quality needs is a browser plugin, which must be explicitly installed by the user.
A large number of users do not like installing plugins for their browsers. In the past, badly implemented plugins would frequently crash the browser and use up huge amounts of CPU and memory. Plugins could also expose security threats, allowing access and control of the user’s computer by external parties without the user’s consent.
Of course every piece of software potentially has these issues, but the fact that some plugins did not update frequently enough and that external developers could not inspect their source code did not help to improve their real or perceived threat.
Modern browsers usually run plugins in a separate process in order to alleviate some of the security and stability problems listed above. If the plugin crashes it only takes down its own process, not the whole browser, and if there are security issues they only compromise the limited resources of the plugin process.
If the plugin process is using too much CPU it will only stall its own process and the browser can continue to respond. Browsers also now routinely check for updated versions of plugins and warm the user of required updates. Some also blacklist plugins known to be problematic.
So, although the situation has improved a great deal, users will still think twice before installing plugins, and many users will simply refuse to install them.
The approach of the Turbulenz engine has several aspects to it:
- We support as many of the APIs exposed by the browsers as possible, providing lower quality fallbacks or low performance fallbacks when needed.
- We encourage browser developers to implement or improve the APIs they expose, frequently through direct contact with their development teams and by logging bugs and feature requests in their bug reporting systems.
- Our pages promote the update or migration to browser versions that support required features for high quality games.
- We provide support for our own minimal plugin, or for plugins developed by third parties, when there is no other choice.
- We provide a set of low level libraries to abstract away the functionality that can be provided either by the browser or by plugins, so we can support both of them at runtime with no change at all to game code.
We consider our plugin strategy as transitional. As support for HTML5 and related APIs improves and we no longer need the features provided by our plugin our low level libraries will use the browser functionality. Note that this requires no change to game code and no action on the part of end users.
To learn more about the Turbulenz Engine technology see the SDK documentation, publicly available at http://docs.turbulenz.com/.
Asset Formats - JSON
The JSON object provides support for JavaScript Object Notation, which is useful for serializing data to and from strings. We recommended it as the best way to generate JavaScript objects at runtime from serialized data.
Modern browsers implement JSON support with optimized C++ code so in many cases it will outperform any other serialization method, particularly those that are not natively supported by the browser and require implementation in JavaScript.
Old browsers do not have JSON support, and in this case emulation in JavaScript is available.
Timers
The traditional functions setTimeout and setInterval only had a resolution of 10-15ms and didn’t provide any context information for the browsers. The first issue meant that smooth animations at traditional 30FPS or 60FPS were almost impossible. The second issue made it hard for the browser to guess the purpose of a given callback, and whether or not the code could gracefully handle being called less often (for example when the tab went to the background or became hidden). Modern browsers have increased the resolution of these traditional functions to about 4ms, but this is still not enough of an improvement for games. Thankfully, there are now alternative APIs for timing and animation.
requestAnimationFrame
The requestAnimationFrame API provides a more optimal and accurate callback for updating dynamic content in an attempt to fix the issues with setTimeout and setInterval. Browsers will try to call the callback at 60FPS, dropping to a lower frequency if the page goes to the background. Some browsers accept an optional parameter that specifies the HTML element to be updated by the callback. In this way the browser can optimize the re-composition of the page.
The API behaves like the original setTimeout in that you have to keep calling it if the callback is to be invoked repeatedly. The API took a while to standardize across browsers so code should try all the different names the function was given during its conception:
var requestAnimationFrame = (window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame);
if (requestAnimationFrame)
{
var update = function updateFn()
{
// Perform rendering update
...
// Request next callback
requestAnimationFrame(update, canvas);
};
// Request initial callback
requestAnimationFrame(update, canvas);
}
High Resolution Time
The High Resolution Time API provides the current time in sub-millisecond resolution, more suitable for accurate timing than the Date functionality.
Most modern browsers support this API, although still prefixed with vendor names until the standard is ratified.
When the Turbulenz libraries fall back to the plugin for other functionality, they can take advantage of our implementation of setTimeout and setInterval with sub-millisecond accuracy to provide a solid 60FPS framerate. The issue of giving time back to the browser still needs addressing, and the plugin handles this by disabling rendering when the page goes to the background.
|
This isn't correct. RequestAnimationFrame is using v-synch. It'll try to match the monitor's frequency, not a flat 60 FPS. Try changing your monitor's refresh rate and run a basic RequestAnimationFrame demo in Chrome using the Timeline tab. It'll show the default 60 and 30 FPS range, but the transparent "frame overhead" bars will match the v-synch. For example, for 75Hz the bars should be a bit lower than the 60 FPS line and the frame time should be about 13 ms instead of 16 ms.
"The expectation is that the user agent will run tasks from the animation task source at at a regular interval matching the display's refresh rate. Running tasks at a lower rate can result in animations not appearing smooth. Running tasks at a higher rate can cause extra computation to occur without a user-visible benefit."
This is from the w3c documentation (https://dvcs.w3.org/hg/webperf/raw-file/a43340fd9097/specs/RequestAnimat ionFrame/Overview.html). EDIT: I have no idea why but Gamasutra forces a space in RequestAnimationFrame in the address. Remove it if you wanna check the page.
"This API will take page visibility and the display's refresh rate into account to determine how many frames per second to allocate to the animation."
This is from Microsoft's site (http://ie.microsoft.com/testdrive/Graphics/RequestAnimationFrame/Default .html).
I'm fairly sure that Firefox doesn't synch. I guess that the thing to take away from this is, don't assume that it's going to be 60 FPS.
Actually HTML5 in general is still too shaky to even bother with it for mobile. Prepare for the time when it isn't, but it's just not good enough yet. Take for example Apple removing the trick that let you hardware accelerate animations by using the CSS rotation properties -- you just can't get the performance you need for any but the simplest cases.
"The repaint may occur up to 60 times per second for foreground tabs" and "we don't invoke the callbacks at a rate faster than 60Hz" are from other browser docs.
We do assume that by default the target rate would be 60 FPS, but of course we do code defensively, taking care of spikes or drops. The point is that with requestAnimationFrame it is perfectly possible to easily run at smooth 60 FPS and in many cases that will be the end result.
We did try to use setTimeout and setInterval and we never got smooth animations at 60 FPS.
Yes, mobile is lagging behind...
Is the 45 FPS being measured in real time or averaging? 45 is right between 30 and 60. The drop to 30 FPS would be correct since that's the "next step" in v-synch. To synch with a 60 Hz monitor, the FPS needs to be 60, 30, 15, 12, 10, etc... Though i have noticed myself that for some of my load tests Firefox and Chrome can sometimes stick with ~45 (measured in real time) which doesn't make much sense.