Web Graphics, Part 3: WebGL
- A 3D Canvas
- WebGL ES
- Compiling Shaders
- Passing Data to the GPU
- Overall
The previous articles in this series covered two technologies for drawing 2D vector graphics in a web browser. Part 1 covered the <canvas> tag, which provides a drawing surface and allows you to use JavaScript to draw with a PostScript-like model. Part 2 looked at SVG, which allows you to add vector art and animations to the DOM. This article adds another dimension, as we examine 3D web graphics.
The idea of 3D graphics delivered via the Web isn't new. Virtual Reality Markup Language (VRML) has been around since the early 1990s and was standardized in 1995. Back then, it was severely limited by the available technology. I remember reading glowing descriptions of how VRML would change the world. When I tried it[md]on my 16 MHz 386 with 5MB of RAM and a 14.4 kbps modem[md]I found that it took several minutes to load a VRML scene, and then it rendered one frame every few seconds.
3D hardware acceleration didn't become mainstream until the late 1990s, and VRML's hype had largely died down by then. The standard eventually was superseded by X3D, which provided a similar model but with an XML serialization. To date, no mainstream browsers ship with implementations of either language.
Google tried to encourage 3D web applications with O3D, an open source browser plug-in that provides a set of JavaScript APIs, but so far O3D hasn't seen much widespread use.
Apple shipped support for the <canvas> tag with OS X 10.4 in 2005, and other browsers quickly started implementing it. Mozilla tried extending the <canvas> tag to provide a 3D surface as well as the 2D one that was standardized as part of HTML 5 (discussed in part 1 of this series).
Unlike the other technologies we've considered in this series, WebGL is very new. Mozilla shipped the first prototype in 2006, but it was only in 2009 that the Khronos Group, the organization responsible for the OpenGL family of standards, formed a working group to develop WebGL as an official standard. At the time of writing, no shipping browsers support WebGL, although you can find implementations in the development branches of various browsers.
WebGL is closely related to OpenGL, specifically to OpenGL ES. The rest of this article will look at the parts specific to WebGL, rather than providing an introduction to OpenGL ES, which is a very large topic in itself. If you haven't used recent versions of OpenGL, some parts of this discussion may be difficult to follow.
A 3D Canvas
In terms of HTML, WebGL adds nothing new. The same canvas element that's used for 2D drawing is used by WebGL; however, at the HTML layer, some space is reserved for drawing. The HTML doesn't care whether the drawing is 2D or 3D; it happens without interaction with the DOM or HTML layout trees.
The changes start to happen when you request the drawing context. According to the HTML 5 standard, the argument to the getContext() call on the canvas element must be '2d'. WebGL adds a 'webgl' string and an optional second argument allowing certain features to be disabled:
canvas = document.getElementById('canvas'); context = canvas.getContext('webgl', { antialias: false } );
This example constructs a WebGL context without antialising. Various features such as alpha, depth, and stencil buffers are all enabled by default on a new WebGL context and must be disabled explicitly if not required.
If you try this code, most likely it won't work. Browsers that implement the draft specification are currently using a different context name for easy differentiation between the WebGL 1.0 standard and WebGL draft implementations. Getting a working canvas requires some quite convoluted hoop-jumping:
Unfortunately, the Mozilla developers decided to throw an exception, rather than simply returning undef when you try to get an undefined canvas type, so you need to test whether the context is valid and catch an exception on each attempt. You might request four possible context types: The 'moz-webgl' and 'webkit-gl' context types correspond to Gecko's and WebKit's pre-standard implementations, respectively. The 'experimental-webgl' context refers to the draft specification. The 'webgl' context will refer to the final version of the standard, once it exists.