Intro to WebGL

Ilmari Heikkinen

Who am I?

Ilmari Heikkinen

@ilmarihei | fhtr.org/plus | fhtr.org



Google Chrome Developer Programs Engineer

I write demos, do presentations, write articles

WebGL

What is WebGL?

A Khronos group standard

JavaScript meets the GPU

Fast programmable drawing

OpenGL ES 2.0 for HTML5 Canvas

What can you do with it?

Shader-based drawing

2D graphics

3D graphics

Basic idea

Send a list of points to WebGL

Vertex shader places them on the screen (screen coords run from -1..1)

Fragment shader colors the pixels using vertex shader output

And...?

That's pretty much it.

WebGL is just a fast way to put lots of triangles, lines and points on the screen.

How to transform the vertices and shade the pixels is up to the programmer.

What browsers support it?

Chrome

Firefox

Safari (behind a command-line flag)

Opera (in dev build)

What can you use it for?

Games

Image filters

Data visualization

3D applications

Other things that need fast programmable drawing

Shaders

What are shaders

Shaders are small programs that tell WebGL


where to draw

and

what to draw

Shaders are written in GLSL, the GL Shading Language.

It's kinda like C for graphics.

Vertex shader

Where to draw.

Projects geometry to screen coordinates.

    <script id="vertex" type="text/x-glsl-vert">
      varying float vZ;
      uniform float time;
      void main() {
        vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
        mvPosition.y += 20.0*sin(time*0.5+mvPosition.x/25.0);
        mvPosition.x += 30.0*cos(time*0.5+mvPosition.y/25.0);
        vec4 p = projectionMatrix * mvPosition;
        vZ = p.z;
        gl_Position = p;
      }
    </script>

Fragment shader

What to draw.

Computes the color of a pixel.

    <script id="fragment" type="text/x-glsl-frag">
      varying float vZ;
      uniform float time;
      uniform vec2 size;
      void main() {
        vec2 d = gl_FragCoord.xy - (0.5+0.02*sin(time))*size;
        float a = sin(time*0.3)*2.0*3.14159;
        d = vec2( d.x*cos(a) + d.y*sin(a),
                 -d.x*sin(a) + d.y*cos(a));
        vec2 rg = vec2(1.0)-abs(d)/(0.5*size)
        float b = abs(vZ) / 160.0;
        gl_FragColor = vec4(rg,b,1.0);
      }
    </script>

That's very colourful

Games

WebGL for Games

3D graphics

Fancy shaders

Fast 2D graphics

Examples

Angry Birds uses WebGL to accelerate 2D drawing

Monster Dash does accelerated 2D as well

Gun Bros is an isometric 3D game

Image processing

Image filters are kinda slow in JavaScript

Runs on the CPU

No vector ops yet

Parallelizing with Web Workers possible

WebGL is very fast at image filters

Output pixels are independent of each other

Compute hundreds of pixels in parallel on the GPU

GLSL is very expressive for image processing

Examples

glfx.js - WebGL image filters

Filtering video in realtime

Data Visualization

Data visualization

Sometimes you want to show complex 3D data.

Like a spinning globe of search query languages.

It's kinda difficult with just HTML, so WebGL helps.

WebGL Globe

Applications

Perhaps you want to build a 3D modeler

And make it look nice and smooth.

TinkerCAD is a solid CAD program built in WebGL.

Or print out spaceships

With an animated preview.

ship.shapewright.com is a random spaceship constructor hooked up to a 3D printing service.

Using WebGL

Use a library

Raw WebGL is very low-level and very generic.

(Write your own shaders to do 3D projections and lighting, there's very little built in.)

So, use a library that does what you want.

I'm going to show you a couple examples using Three.js.

Three.js?

Three.js is a JS 3D Engine

Example: Bar graph

      var grid = /* 2D Array */
      var barGraph = new THREE.Object3D();
      scene.addChild(barGraph);

      var max = /* Grid max value */
      var mat = new THREE.MeshLambertMaterial({color: 0xFFAA55});
      for (var j=0; j<grid.length; j++) {
        for (var i=0; i<grid[j].length; i++) {
          var barHeight = grid[j][i]/max * 80;
          var geo = new THREE.CubeGeometry(8, barHeight, 8);
          var mesh = new THREE.Mesh(geo, mat);
          mesh.position.x = (i-grid[j].length/2) * 16;
          mesh.position.y = barHeight/2;
          mesh.position.z = -(j-grid.length/2) * 16;
          mesh.castShadow = mesh.receiveShadow = true;
          barGraph.addChild(mesh);
        }
      }

Bar graph in action

Scatter plot

var scatterPlot = new THREE.Object3D();
var mat = new THREE.ParticleBasicMaterial(
  {vertexColors: true, size: 1.5});

var pointCount = 10000;
var pointGeo = new THREE.Geometry();
for (var i=0; i<pointCount; i++) {
  var x = Math.random() * 100 - 50;
  var y = x*0.8+Math.random() * 20 - 10;
  var z = x*0.7+Math.random() * 30 - 15;
  pointGeo.vertices.push(new THREE.Vertex(new THREE.Vector3(x,y,z)));
  pointGeo.colors.push(new THREE.Color().setHSV(
    (x+50)/100, (z+50)/100, (y+50)/100));
}
var points = new THREE.ParticleSystem(pointGeo, mat);
scatterPlot.addChild(points);
scene.fog = new THREE.FogExp2(0xFFFFFF, 0.0035);

Scatter plot in action

Double-click to animate

Conclusion

WebGL

Open standard

Supported by most browsers

Fast programmable graphics

Hardware-accelerated

Helper libraries for getting things done

The End

Ilmari Heikkinen

@ilmarihei | fhtr.org/plus | fhtr.org