Following research, internal discussions, and optimizations, we’ve managed to pump out a renderer that draws a subset of 2D content anywhere from 6x to 50x faster than is currently possible on the Canvas 2D Context.
We thought about what we wanted to gain from a WebGL renderer, and narrowed it down to three key goals:
- Very fast performance for drawing sprites and bitmaps
- Consistency and integration with the existing EaselJS API
- The ability to fall back to Context2D rendering if WebGL is not available
Here’s what we came up with:
SpriteStage & SpriteContainer
Two new classes, SpriteStage and SpriteContainer, enforce restrictions on the display list to enable aggressively optimized rendering of bitmap content. This includes images, spritesheet animations, and bitmap text.
These new classes extend existing EaselJS classes (Stage and Container) and share the same API, so creating WebGL content is super simple if you’re familiar with EaselJS. Existing content using EaselJS can be WebGL-enabled with a few keystrokes.
This approach allows WebGL and Context2D content to be layered on screen, and mouse/touch interactions can pass seamlessly between the layers. For example, an incredibly fast game engine using WebGL rendering can be displayed under a UI layer that leverages the more robust capabilities of the Context2D renderer. You can even swap assets between a WebGL and Context2D layer.
Finally, WebGL content is fully compatible with the existing Context2D renderer. On devices or browsers that don’t support WebGL, your content will automatically be rendered via canvas 2D.
While it took some work to squeeze every last iota of performance out of the new renderer, we’re really happy with this new approach. It allows developers to build incredibly high performance content for a wide range of devices, and also leverage the extremely rich existing API and toolchain surrounding CreateJS. Below, you’ll find a few demos that show off its capabilities.
A very popular (though limited) benchmark for web graphics is Bunnymark. This benchmark simply measures the maximum number of bouncing bunny bitmap sprites (try saying that 5 times fast) a renderer can support at 60fps.
The following table compares Bunnymark scores using the classic Context2D renderer and the new WebGL renderer. Higher numbers are better.
|2012 Macbook Pro, Firefox 26||900||46,000||51x|
|2012 Macbook Pro, Chrome 31||2300||60,000||26x|
|2012 Win 7 laptop, IE11 (x64 NVIDIA GeForce GT 630M, 1 GB VRAM)||1900||9800||5x|
|FxOS 184.108.40.206-prerelease (early 1.2 device)||45||270||6x|
|Nexus 5, Firefox 26||225||4400||20x|
|Nexus 5, Chrome 31||230||4800||21x|
Since these numbers show maximum sprites at 60fps, the above numbers can increase significantly if a lower framerate is allowed. It’s worth noting that the only FxOS device we have in house is an early FxOS 1.2 device with a relatively low-powered GPU, yet we’re still seeing significant performance gains.
Example: Sparkles Benchmark
This very simple demo was made to test the limits of how many particles could be put on screen while pushing the browser to 24fps.
Example: Planetary Gary
We often use the Planetary Gary game demo as a test bed for new capabilities in the CreateJS libraries. In this case, we retrofitted the existing game to use the new SpriteStage and SpriteContainer classes for rendering in WebGL.
This was surprisingly easy to do, requiring only three lines of changed or added code, and demonstrates the ease of use, and consistency of the new APIs. It’s a particularly good example because it shows how the robust feature set of the Context2D renderer can be used for user interface elements (ex. the start screen) in cooperation with the superior performance of the WebGL renderer (ex. the game).
Even better, the game art is packaged as vector graphics, which are drawn to sprite sheets via the Context2D renderer at run time (using EaselJS’s SpriteSheetBuilder), then passed to the WebGL renderer. This allows for completely scaleable graphics with tiny file size (~85kb over the wire) and incredible performance!
Follow @createjs on twitter to stay up to date with the latest news and let us know what you think — thanks for reading!