Thursday, July 07, 2011

Accelerating ImpactJS With WebGL

First of all, I want to say that I am not claiming any significant credit for this. The cake was already for the most part complete. I just spread a little icing and added a cherry on top.

One of the problems with the implementation of HTML5's Canvas on the Mac is that it is not hardware accelerated (at least in Chrome, which is what I test with). Consequently, all of the drawing to the canvas is done in software, which is a shame seeing as on most computers there is a perfectly capable graphics card sitting idly by while the processor does all of the work. The end result was that my top-of-the-line MacBook Pro struggled to get 30-40fps which a two year old crappy laptop running Windows (which has a hardware-accelerated canvas in Chrome) got a smooth 60fps. Hell, even Windows Chrome running in VMWare on my Mac got 60fps.

Creatures & Castles for the Chrome Web Store uses the ImpactJS framework, which has a rather useful plug-in system to override and replace core parts of the functionality. A while back, the creator of ImpactJS tweeted that he had played with Corban Brook's WebGL Canvas Wrapper API created in Javascript. The only catch was that it did not support alpha. Luckily, there was a fork here by FuzzYspo0N (Sven Bergström) which had implemented limited transparency in an older version of the original project.

It was simple enough to look at the shader modifications in the alpha-enabled version and apply them to the absolute latest version of Corban's original. I even extended the alpha support to other drawing types supported by canvas (e.g. line and shape) so that the alpha was respected by all of the API calls (at least all that I have tested). Okay, so that's the icing... How about the cherry?

I extracted the plugin from the ImpactJS demo game here, but I wanted a plugin for ImpactJS that would automatically probe to see if the browser supported WebGL and fall back to standard 2D if it did not. Well, with the current implementation of the WebGL wrapper, it throws an exception if WebGL is not supported. (Note: I'm not to keen on using this as a detection mechanism, and may well improve this in future). In any case, with all of the browsers I've currently tested it on, the plugin has the desired effect of using WebGL if it's available and falling back to Canvas2D if not. It's a bit quick and dirty, but it works.

The end result? A smooth 60fps on my MacBook Pro. Hooray!

The code can be found here. Suggestions for improvements and any bug fixes are welcome!

Just for completeness, here is the obligatory before and after comparison:

Before (standard Canvas 2D)
After (WebGL)