• ,

Hello WebGL!

I heard about WebGL more than a year ago, and from that every moment I wanted to jump into it. But my first experience didn't show up until very recently, as I started to work on a game that runs in a browser.

Before we start, I would like to mention that this is not a tutorial about WebGL. There are a lot of very good ones in the web (check the references at the bottom). Instead, I decided to go in a different direction, writing about my experience with WebGL, both the good side and the bad one.

So, what is WebGL?

Simply put, WebGL is a 3D rendering in a web browser (and here comes the good part) without the need of an external plugin. Although it's still a bit green in some topics, most browsers have a decent support for it (except, of course, IE) and there are a lot of very interesting things, like this:

Game Development: Hello WebGL!Florian Boesch’s Deferred Irradiance Volumes

Why WebGL?

As a graphics programmer, you'd probably faced situations like this: «Hey, let me show you what I did!!! Just wait a second, I need to compile it first. Oh, you have Windows? No problem, let me tweak this a bit. And that over there. Crap, it doesn't load anymore. Never mind, I have an old one built on my iPhone...». Unfortunately for me, this is quite common.

So, one of the most important benefits that WebGL provides is «availability». I create something, publish it and then everyone can see it. No need to maintain branches of code for each platform. No need to wait for compile time. No need for me to be present when people see it. OK, the last one is a double-edged sword, but you get the idea.

Another great benefit of working on a browser is rapid prototyping. It's very common for game developers to work with some kind of scripting language like Lua or Python in order to avoid long build cycles when testing game mechanics. In WebGL, we're always using a scripting language (Javascript), and that leads to a very fast development cycle. And if we're using a browser with development tools such as Chrome or Firefox we can even change the code on the fly without the need of reloading the page.

Game Development: Hello WebGL!Olafur Eliasson's ‘Little Sun’ Sunlight Graffiti

Javascript

This was the first bump in the road. I never really like Javascript and I tried to avoid it whenever possible. Why? Because while in languages like C++ we would write:
result = a.translate + (a.rotate * b.rotate);

In Javascript, we end up with something more like this:
quat4.multiplyVec3(a.rotate, b.translate, tempVec3);
vec3.add(tempVec3, a.translate, result);

The lack of operator overloading makes Javascript very cryptic when dealing with math operations (which are cryptic by definition). And that is exactly what we do most of the time when working with graphics. Therefore, you end up over-documenting low-level parts of the code as you try to explain what exactly are you attempting to calculate.

But Javascript does have some very interesting features. Since it doesn't have classes, you need to think about the things in a different manner. It's still OOP, but different. Everything is very dynamic, avoiding the need of abstract classes or complicated double of triple dispatches in order to understand what are dealing with.

In my current project I'm using a component-based approach for extending nodes in a scene and, while I'm basing my design in a previous implementation that uses C++, the JS version of it far simpler. Does the component include an «update» member? If so, call it. If not, continue with the next one. You need to invoke a particular method of your physics component? No problem. Get the component from its own node and use whatever you need without casting it. Really simple.

Javascript does not have namespaces, so I'm making use of RequireJS in order to keep things organized into logical modules. RequireJS also provides tools for code optimization and compression (I don't like to call it 'compilation'), but I haven't taken advantage of them yet.

Game Development: Hello WebGL!AlteredQualia's Doom 3 Character Loader

The WebGL API

Having worked on iOS for the past four years gave me a good understanding of OpenGL ES, so my first hours with WebGL I felt very natural.

Being a shader-based API, you can move a lot of calculations like vertex morphing or per-fragment lighting to the graphics processor, saving some processing power for other tasks, such as physics or sound. There's no support for geometry shaders as far as I know, though.

There are some limitations, such as not being able to use multiple render targets (and therefore you can't have deferred rendering in the traditional way), but for the most of the time you won't be missing them. Truth is, if you're aiming to a very complex render path, chances are you won't be able to run that on Javascript anyway. In cases like this you may want to look at Google's Native Client, which lets you run C++ code in the browser, but that's a story for another time.

Game Development: Hello WebGL!HDR Illumination and Reflections by Pierre Lepers

Is it fast?

To be honest, I was expecting some performance issues with Javascript but, to my surprise, I couldn't find any. Working with WebGL/Javascript feels very similar as a programming on a mobile device. It's important not to work with an extremely complex scene, keeping a low number of drawable objects. Yet, geometry can have a pretty decent amount of detail since you can use vertex buffers to store them into VRAM.

The garbage collector could be a problem if not handle properly. You need to be very careful when instantiating new objects or else you will end up with a crappy performance and lots of wasted memory. But then again, this is nothing comparing to what we had dealt before with other garbage collected languages.

So, I like to say that WebGL is «fast enough». Javascript escalates well based on the hardware, but it's not C or C++. As long as you avoid an epic battle with thousands of soldiers fighting each other, you'll be fine. There are other constraints more critical than Javascript when working on web-based 3D graphics, which leads me to the next topic.

One thing that disappointed me is that performance in mobile devices is still not good enough. I have a modern smartphone and it can barely handle relatively simple demos. I guess we're still stuck here with a native code…

Game Development: Hello WebGL!Jasmine Kent’s Trigger Rally

Assets

Now here comes THE problem when developing games in a browser: Assets. There are two big issues with assets: asynchronous downloads and loading times.

In web, every asset other than the base HTML is loaded asynchronously, forcing us to use some sort of asset manager or streaming strategy in order to ensure that assets are initialized at the time the scene is executed. I'm not saying that you need to load them all at the beginning of the game, since asynchronous loading does have some benefits. But you need to make sure they are properly loaded before using them, since neither Javascript nor WebGL does a good job at reporting errors, and you will end up with some weird artifacts. If your texture is not in memory by the time you're calling glEnable, there are chances that you'll end up with a black object instead of an exception. On the other hand, if you attempt to render a scene before you load and compile the corresponding shaders, you'll probably get a crash but don't expect a nice error message.

Concerning the loading times, while we're technically able to render beautiful landscapes with lots of trees and wildlife, keep in mind that you can't expect users to wait 50 minutes to download 1.5GB of data. After all, you're still rendering a web page. This is a true constraint for web-based game. Yes, you can still use some techniques to store data offline in order to avoid re-downloading them again the next time, but users expect to load pages lighting-fast and that limits the complexity of what we can achieve. Streaming is your friend here, loading assets on demand, but these techniques are never easy.

And last, but not least, WebGL does not provide any mechanism to work with known file formats, neither for textures nor for models. You need to code the parsers by yourself, much as you would do in any other OpenGL API.

Closing comments

This turned out to be a much longer post than I expected. There are a couple of things that I'll talk about in a later post, especially after gaining some more experience. For the moment, I cannot show much of what I'm doing other than the library that I'm working on, CrimildJS, a small WebGL-based game framework that I'm using in my current project. It's at a very early stage of development, but it's growing fast.

Until next time.

References

4 comments

dvaruh
This topic is a real discovery for me. And even, if it was longer, I was ready to continue to read ;). Thanks a lot.
jviaches
Multicross platform is a great asset for engaging as much end users as possible. It should avoid situation in which developer should write the same application on Android, Iphone or Windows Phone. And its really great!

By the way hhsaez , is it working as singleton application (not as a web page) on Iphone or on Android from your expirience?
hhsaez
jviaches It needs a web browser to run. On mobile devices you have OpenGL ES, which is the «father» of WebGL (WebGL is based on the OpenGL ES 2.0 specification). I attempted to load a WebGL example with my Galaxy S3 (using Opera browser), but it turns out Javascript is not good enough for mobile devices yet. So I believe you should take advantage of native languages like Objective-C or Java (or even C/C++) whenever possible.
jviaches
Thanx for the detailed answer.

Add comment