- a lightweight WebGL renderer for Android and Ouya (WIP)
Boris van Schooten, 4 Sept 2015 (email@example.com)
Latest news: gles.js is now on github! Note that the text below is old and needs to be updated.
After being unsatisfied with existing Android WebGL engines, I decided to create my own engine.
Chrome Android refuses to run WebGL on many (old and new) devices, unless you use the ignore blacklist option under the section "careful, these experiments may bite". Performance is not so good on low-end devices. For example, most games I played at html5games or playzap ran at 5-10fps in Chrome on my tablet, even if they had like 5 moving sprites. This is a cheap tablet, but it generally runs 3D games smoothly. And no, this is by no means the only device with this problem.
For those who want to package their html5 game as an app (I certainly do) there is CocoonJS and Crosswalk (based on Chromium). I did find CocoonJS significantly faster than Chrome, but it still failed to produce sufficient speed on my tablet. It sometimes also crashes or glitches, or input or sound do not work. It's kind of hard to figure out why because it's not open source. The huge file that the cloud compiler produces is not encouraging either (I got a 10Mb-22Mb APK without any clue as how to make it smaller). The only other html5 wrappers I know are Ejecta-X (2D canvas only), and Phonegap (based on WebView, which will not have WebGL until Android L, and does not have 2D hardware acceleration in Android 4.4 up to 4.4.2).
Since WebGL is virtually identical to OpenGL ES 2.0, which is available on any recent Android device, I was surprised with the low performance. I've seen my native apps do so much better. WebGL on mobile should be a better fit than WebGL on desktop, not worse. My suspicion is that Chrome/Chromium has a lot of security/safety/sandboxing overhead, and/or uses a renderbuffer compositing scheme for handling canvas scaling and HTML element overlays that doesn't play well with cheaper devices. CocoonJS probably has some of the same problems, in particular with regard to compositing.
At this point I have two games and some pixi.js and phaser.js examples running, and it looks good! I managed to whittle down the base APK size to 1,3 Mb. I've tested it against Chrome on several devices, but I guess evidence remains somewhat anecdotical. My experience is that gles.js indeed runs faster than Chrome, speed difference varies across devices. It's like between 50% faster and 5 times (!) faster. It also runs smoother, that is, where I often see small hiccups in Chrome even on fast devices, gles.js runs the same code silky smooth 60fps, which has become the norm on Android nowadays. And my limited testing with CocoonJS also indicates it's faster than their implementation.
UPDATE: gles.js now has Ouya game controller support through the gamepad API. I'm now working on local storage.
UPDATE: gles.js now has proper pause/resume handling. It no longer exits or crashes when pausing/resuming. Sound is also nicely paused. Note that the demos are not yet updated, but the games are.
10,000 sprite demoThis was my first demo. Updates and draws the sprites in JS, with the code compatible with WebGL. It manages 10,000 sprites animating at 60fps on my tablet. Note that Chrome runs this demo at about 10fps on my tablet, and CocoonJS at 22fps. See below for more performance info.
Download/view proof of concept demo:
First games running in gles.jsI got my game Nyan Can vs Flappy Bird Clones running in gles.js without changing the code! This was the reason I started on gles.js. I just didn't care to recode my WebGL games in Java.
When it first ran, I was happy that it ran at a steady 30fps! It wasn't the full 60fps I had hoped, but it was quite useable. This game runs at 5-10 fps in Chrome, so it's really much faster. I tried optimising it a bit here and there (I found that GL calls are really slow on mobile, so my code was and still is really suboptimal), and at this point got the fps up to 45-50. Chrome manages the same optimised code at no more than 10 fps, and CocoonJS at 25-30 fps. It also runs 60fps on the Ouya (now with gamepad controls!), which means it's much faster than Ouya's Android canvas, which is what I was aiming for. Note that I still have to do more testing, so consider this alpha.
Pixi.js examplesPixi.js runs without modification now, and I a currently going through the examples to make sure the different features work. I still have to do a few more examples. Here are some highlights.
TODO: Fonts don't work yet. Bitmap fonts should be easiest to get running after I adapt my DOM parser to read generic XML.
Phaser example gamesI got the first Phaser example games up and running! UPDATE: the games now have proper pause/resume handling. Unfortunately you cannot restart these games, so you need to kill the app to play again.
Where to go from hereI want to provide the app both as a "viewer" which loads resources from the SD card, or from a web site, and as an easy to package APK (just put your stuff in the assets/ directory and apk it). Also I plan to release the source, which should be quite hackable due to its simplicity.
I'm almost ready for a release! I still want to improve error reporting. Right now it does not report the line numbers of syntax errors.
After that I want to do the following in the short(er) term:
Appendix: Preliminary tests
I tested the demo on different devices. Up till now, it worked on all tablets I found, and also on all new phones. It does not work on some old phones, like my own (those with armv6 architecture, if I'm not mistaken). Most tablets and almost half the cheap phones manage the demo at 60fps. In fact, generally it runs better on tablets than on desktop PCs, as PCs often have trouble managing 60fps full-screen. See the overview below.