WebGL is coming

4 years ago

WebGL is a new open technology for building HTML5 games. I enables developers access to lower level graphics APIs allowing high performance and 3D transformations. All fully hardware accelerated. WebGL is based on OpenGLES 2.0 and it basically works in three steps. First you write small shader programs and send them to be run on your graphics card. Then combine your vertex/color/texture/etc data to the data buffers and send the buffers to the graphics card. And finally tell your graphics card to draw the data inside the buffers using the shader programs. Good introduction to OpenGL ES 2.0 can be found from Jeff LaMarche blog. Luckily you don’t have to know everything about WebGL to use it in LimeJS. The WebGL renderer can be used as a simple on/off switch with no further knowledge needed. As an extra we will include Closure Library style WebGL framework methods that we use for writing the renderer so you can use it for your custom WebGL related work.

You can follow along WebGL related development in the WebGL branch on Github. Its not in any way stable or feature complete at the moment but may be interesting for you to follow along when features appear. This also means that we are very open to suggestions about all aspects what it should do, what it should not and how it should be implemented. As there is no features yet marked ready there is a very good change your own idea can make into it.

The main benefit WebGL gives is better performance and ability to draw 3D contents on WebGLContext shape. WebGL renderer ‘lime.Renderer.WEBGL’ can be used as any other renderer, so any shape accepts it on it’s ‘setRenderer()’ method. But there are some aspects that make it special. The startup time of starting a new WebGL context is pretty high so it may not be very usable to switch between WebGL renderer and some other renderer method. Also it does not make much sense to have many WebGL contexts on the screen - the benefits of using WebGL start to appear when it can draw lot of stuff in one context. So usually we would see it used for whole Scene objects and not so much for independent elements.

So how much faster will it be? Not too much actually. Don’t expect 10 times performance gain unless your current browser’s DOM or Canvas implementation is very slow. Some benchmarks will show that magnitude change is possible but it really is for certain tasks only. OpenGL is really good if you have many static triangles(big model) and you apply a 3D transformation to them all together. You will be abled to use this method via WebGLContext shape that lets you have exact low level control of everything that is drawn using our WebGL helper library(same way as you can use CanvasContext shape currently). But for the WebGL renderer we need to write middleware that converts LimeJS nodes to vertex arrays and draws them using right shaders. This middleware will probably be the bottleneck, not the WebGL draw commands themselves.

Here is a simple example of 3 renderers in action. It just draws 1000 sprites on the screen and then resizes and rotates them all in random factors in every frame. You can compare the performance by switching between renderers and comparing the FPS value. Remember that this is not something that WebGL is very much suited for, more like a worst case example because every box moves independently.

Code to draw and animate the sprites is:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
var numboxes = 1000;

for(var i=0;i<numboxes;i++){

    var sprite = new lime.Sprite().
        setSize(10+Math.random()*20,10+Math.random()*20).
        setPosition(Math.random()*600,Math.random()*400).
        setFill(Math.round(Math.random()*255),
                Math.round(Math.random()*255),
                Math.round(Math.random()*255));
    layer.appendChild(sprite);

    var seq =  new lime.animation.Spawn(
        new lime.animation.ScaleBy(1+Math.random()).setDuration(7),
        new lime.animation.RotateBy(360*Math.random()).setDuration(10)
        );

    var anim = new lime.animation.Loop(new lime.animation.Sequence(seq,seq.reverse()));

    sprite.runAction(anim);

}

Full code is available on github and here is the LIVE SAMPLE (needs WebGL capable browser: Chrome9+,Firefox4,Webkit Nightly).

In couple of days I’ll write more in depth about the WebGL library features and design goals. Stay tuned.