JavaScript Canvas - WebGL 3D
Written by Ian Elliot   
Monday, 06 December 2021
Article Index
JavaScript Canvas - WebGL 3D
Vertex Shader
Fragment Shader
Connecting With Shaders
Vertex Data

Graphics 3D is the utimate.  In this extract from Ian Elliot's book on JavaScript Graphics we look at how to get started with WebGL 3D

Now available as a paperback or ebook from Amazon.

JavaScript Bitmap Graphics
With Canvas




  1. JavaScript Graphics
  2. Getting Started With Canvas
  3. Drawing Paths
      Extract: Basic Paths
      Extract: SVG Paths
      Extract: Bezier Curves
  4. Stroke and Fill
      Extract: Stroke Properties 
      Extract: Fill and Holes
      Extract: Gradient & Pattern Fills
  5. Transformations
      Extract: Transformations
      Extract: Custom Coordinates 
      Extract  Graphics State
  6. Text
      Extract: Text, Typography & SVG 
      Extract: Unicode
  7. Clipping, Compositing and Effects
      Extract: Clipping & Basic Compositing
  8. Generating Bitmaps
      Extract:  Introduction To Bitmaps
      Extract :  Animation 
  9. WebWorkers & OffscreenCanvas
      Extract: Web Workers
      Extract: OffscreenCanvas
  10. Bit Manipulation In JavaScript
      Extract: Bit Manipulation
  11. Typed Arrays
      Extract: Typed Arrays 
  12. Files, blobs, URLs & Fetch
      Extract: Blobs & Files
      Extract: Read/Writing Local Files
      Extract: Fetch API **NEW!
  13. Image Processing
      Extract: ImageData
      Extract:The Filter API
  14. 3D WebGL
      Extract: WebGL 3D
  15. 2D WebGL
    Extract: WebGL Convolutions




This book has so far been about 2D graphics with Canvas using the standard graphics context. You will hear people say that if you want to do 2D graphics then a good way is to use WebGL. The reason is that WebGL is GPU-accelerated and hence has the potential to provide very fast animation. It also provides 3D graphics and animation. As a result learning it seems like a good investment – and it is, but only if you are serious about graphics. There is a steep learning curve associated with WebGL and in this chapter we start from the very basics and work up to some simple graphics with the intention of letting you see how involved it all is. In the next chapter we look at the slightly simpler problem of using WebGL for 2D graphics.

Using WebGL isn't easy for several reasons. Generally, the documentation isn't WebGL specific and simply refers you to the OpenGL/ES documentation pointing out differences. Even if you do know OpenGL, there are some surprising and unwelcome differences between it and the slightly more primitive WebGL. It all makes it difficult to get started on a 3D project.

The project we are about to make a start on, to draw a simple triangle, is going to presented as a single long function and it is not going to use any "helper" functions or any elaborate ways of doing things. The purpose of this example is to show you how things work with code that is simple and direct. While this is good from the point of view of understanding what is happening, when you start work on a real program you need to break it down into sensible functions, you need helper functions to keep the code compact and an "elaborate" way of doing something may turn out to be the best.

You can use any WebGL-supporting browser, but this example is based on using the latest Chrome.

The Canvas and the Viewport

There is a lot of initialization to do before you can start drawing anything and this is the case with most 3D programs. WebGL is particularly bad when it comes to lengthy initialization - there is nothing much that can be done about this. The first thing to do is set up a web page complete with a canvas object that we can use to draw on:

function createCanvas(h, w) {
  var c = document.createElement("canvas");
  c.width = w;
  c.height = h;
  return c;
function draw3d(){
  var gl= document.body.

You should now test that the variable gl really does have a reference to the WebGL object, but for the sake of simplicity let's just assume it does.

The webgl context will return a WebGL 1 or WebGL 2 context depending on what the browser supports. WebGL 1 is supported by all major browsers apart from Safari. WebGL 2 uses a slightly modified form of shader language, but unless you enable this it is backward compatible with WebGL1. For this reason the rest of this chapter uses WebGL 1 and its shader language, even though there are some efficiency improvements in WebGL 2.

Finally we have to set the WebGL viewport to the area of the Canvas object that we want to use to render the 3D graphics. In most cases this is the whole of the Canvas:

gl.viewport(0, 0, canvas.width, canvas.height);

Shader Theory

The next standard initialization task is to set up a vertex and pixel shader. If you have used other 3D frameworks you might not be used to this idea, but modern graphics hardware has a programmable pipeline and WebGL and OpenGL support this.

There are no default rendering modes that you can fall back on - you have to specify how you want to process the 3D points and you have have to specify how to render them. There are no lights, no lighting effects and so on, unless you provide the shader code for it. This can make getting started more difficult, but in practice you can "borrow" standard shaders to create the lighting and rendering effects you want. When you become an expert then working out new shaders simply adds to the fun.

In most cases you have to supply two shaders - a vertex shader and a pixel, or fragment, shader. The vertex shader is all about how the point that you specify in 3D space is converted to the point that is plotted on the screen. It provides the transformation and projection processing and generally you use it to apply transformation and projection matrices onto the raw 3D data. The fragment shader is responsible for setting the color of the pixels that are within the area specified by the vertices. Exactly how it does this can be as simple as assigning a fixed color or as complex as working out what the color should be based on what light is falling on the surface in a 3D scene.

The whole point is that everything that happens is programmable using the shader code. In addition it is worth knowing that your shader code is executed in parallel by hundreds of processors – this is why GPU graphics are much faster than CPU graphics.

Last Updated ( Monday, 06 December 2021 )