HTML and CSS Reference
As graphics APIs evolve, they open up additional parts of the pipeline and offer new ways to perform more work
with fewer calls. In the OpenGL world this functionality is exposed through extensions. OpenGL extensions allow
developers to try new functionality and provide a path for promotion into the core specification. WebGL follows this
same model and contains a number of extensions that can reduce the number of calls to the API.
It is important to note that there are no guarantees that an extension will be available, so relying on their presence
can erode the number of potential users for the application. Unless the extension is widely supported, a fallback will
be required for those users. A site such as WebGL Stats ( http://webglstats.com ) , can give a good indication of what
WebGL implementations in the wild have available. On the plus side all the extensions that will be examined here are
present in the WebGL 2.0 specification.
Vertex Array Objects
When preparing to draw geometry, the buffers holding the vertex data need to be bound. During this process, the
attributes, such as the positions and texture coordinates, must be specified for the vertex shader. Optionally, an index
buffer can be specified. All this results in a number of calls to WebGL. With the vertex array object (VAO) extension,
these calls can be minimized.
A VAO object keeps the vertex buffers bound and all the attributes specified. It even hangs on to the index buffer
in use. The best way to visualize the functionality is to think of a sound recorder. The VAO is bound to the pipeline, the
commands are issued, and the results are held in the object. When needed again, the VAO is pressed into service, and
the commands are played back. Thus, to render geometry, only a single call is required to set up the vertex and index
The VAO extension is the easiest extension to support, as its presence is never integral to rendering. If it's there,
the number of calls can be reduced, but if it's not, the user isn't missing any graphical goodies.
Modern rendering techniques rely on making multiple passes over the same data, with each pass accumulating
a different set. An example of this is deferred shading, a screen-space shading technique. In deferred shading the
lighting is decoupled from the rendering of a model. The algorithm renders to a geometry buffer (G-buffer), which
contains, at minimum, the position, the color information, and normal data for a pixel. If only one render target can
be specified at a time, then the scene needs to be rendered once for each target. This involves a lot of overhead. With
the draw buffers extension, multiple render targets are supported in WebGL.
WebGL allows the creation of framebuffer objects (FBOs), which can be backed by textures. With the draw buffers
extension the framebuffer can be specified with multiple attachments. In the case of deferred shading, there would be
a target for position, normal, and color. The fragment shader would then specify an index into gl_FragColor to target
the output at the different components. Once the scene is done, these textures are used to create the final image by
applying lighting, based on the information within the textures.
Although the draw buffers extension allows amazing effects in the browser, handling a case in which the
extension isn't supported on the device is fairly complex. As mentioned earlier, each geometry will have to be drawn
once for each target, and shaders will have to be authored to handle outputting each component. Also, note well that
rendering the scene multiple times may not be possible within the allotted time frame.
In a three-dimensional scene it is quite likely that there are multiple objects within the scene sharing the same
geometry. Commonly, this involves things such as vegetation, trees, and grass but also extends to characters.
However, each of these instances has different parameters to give some amount of uniqueness, for example, different
colors. Rather than rendering each mesh one at a time, the hardware allows many geometry instances to be rendered
with one call. This functionality is afforded through the instanced arrays extension.