Using WebGL in your app

The HTML5 Canvas API allows you to draw in only two dimensions. Using Web Graphics Library (WebGL), you can show interactive 2D graphics and 3D graphics within any modern web browser (Internet Explorer 11 has only partial support for WebGL) without the use of plugins. WebGL elements are drawn on a canvas element, and can be combined with other HTML elements. Programs that use WebGL are a mixture of Dart (or JavaScript) code for control, and are of specific WebGL shader code. This shader code is executed on the computer's Graphic Processing Unit (GPU), allowing GPU-accelerated usage of physics effects and image processing as part of the web page canvas, so we have real parallel processing here!

WebGL provides a low-level 3D API; mastering it needs more than a recipe, probably a course or book on its own. However, this recipe will provide you with the basics in the webgl project and we point to some links to get further information.

Look at the code of the project webgl. When executed, we see a rectangular red point on a black surface. When we click on the surface, new points are shown:

Using WebGL in your app

Drawing with WebGL

How to do it...

Start using WebGL by performing the following steps:

  1. First, go to http://get.webgl.org/ to determine if your browser and GPU support WebGL; you should see a spinning cube.
  2. The webgl.html page simply defines a <canvas> tag on which we will draw, using the following code:
    <canvas id="webgl" style="border: none;" width="500" height="500"></canvas>
  3. To use WebGL in the code, import the dart_webgl package:
    import 'dart:web_gl';
  4. Now define the shader code for the drawing:
    // Vertex shader program
    var VSHADER_SOURCE = '''attribute vec4 a_Position;
    
                         void main() {
     
                         gl_Position = a_Position;
    
                         gl_PointSize = 10.0;
     
                         }
    '''; 
    // Fragment shader program
    var FSHADER_SOURCE = '''void main() {
    
    gl_FragColor = vec4(1.0, 0.0, 0.0,      1.0);
     // Set the point color
                         }
    '''; 

    To set the vertex coordinates of the point to a fixed value, use the following code:

    gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
  5. The main() function starts by getting a reference to the canvas and the 3D rendering context:
    void main() {
      // Retrieve <canvas> element
      var canvas = querySelector("#webgl");
      if (canvas == null) {
        print('Failed to retrieve the <canvas> element'),
      }
      // Get the rendering context for WebGL
      RenderingContext gl = canvas.getContext3d();
      if (gl == null) {
        print('Failed to get the rendering context for WebGL'),
        return;
      }
  6. Then, the shader code must be compiled and linked to the code:
    // compiling the GPU code
      Shader fragShader = gl.createShader(FRAGMENT_SHADER);
      gl.shaderSource(fragShader, FSHADER_SOURCE);
      gl.compileShader(fragShader);
    
      Shader vertShader = gl.createShader(VERTEX_SHADER);
      gl.shaderSource(vertShader, VSHADER_SOURCE);
      gl.compileShader(vertShader);
    
      Program program = gl.createProgram();
      gl.attachShader(program, vertShader);
      gl.attachShader(program, fragShader);
      gl.linkProgram(program);
    
      if (!gl.getProgramParameter(program, LINK_STATUS)) {
        print("Could not initialise shaders");
        return;
      }
      gl.useProgram(program);
  7. We then get an index to the location in a program of the named attribute variable a _Position:
    var a_Position = gl.getAttribLocation(program,  'a_Position'),
      if (a_Position < 0) {
        print('Failed to get the storage location of a_Position'),
        return;
      }
  8. We register the event handler to be called when the mouse is clicked:
    canvas.onMouseDown.listen((ev) => click(ev, gl, canvas,   a_Position));
  9. Specify the color to clear <canvas>. Clear the canvas and draw the point:
      gl.clearColor(0.0, 0.0, 0.0, 1.0);
      gl.clear(COLOR_BUFFER_BIT);
      gl.drawArrays(POINTS, 0, 1);
     }
  10. The click handler uses an array g_points to remember the mouse click positions:
      List<num> g_points = new List<num>();
    
      void click(ev, RenderingContext gl, canvas, a_Position) {
       var x = ev.clientX; // x coordinate of a mouse pointer
       var y = ev.clientY; // y coordinate of a mouse pointer
       var rect = ev.target.getBoundingClientRect();
    
    x = ((x - rect.left) - canvas.width / 2) / (canvas.width / 2);
    y = (canvas.height / 2 - (y - rect.top))/ (canvas.height / 2);
    
       // Store the coordinates to g_points array
       g_points.add(x);
       g_points.add(y);
    
       gl.clear(COLOR_BUFFER_BIT);
    
       var len = g_points.length;
       for (var i = 0; i < len; i += 2) {
         // Pass the position of a point to a_Position variable
    gl.vertexAttrib3f(a_Position, g_points[i],            g_points[i + 1], 0.0);
          gl.drawArrays(POINTS, 0, 1);
       }
    }

How it works...

The shader code in the fourth step consists of a vertex shader program (to draw the shape boundaries) and fragment shader (for colors, texturing, and lighting) program; they are hard coded in strings assigned to the constants VSHADER_SOURCE and FSHADER_SOURCE.

The piece of code in the sixth step looks daunting, but don't worry, this code can simply be reused in other drawings.

Step 7 is necessary to make a connection between the a_position variable in the shader code, and the variable with the same name in Dart. Notice that the click event handler in steps 8 and 10 needs the GL context and canvas as second and third parameters.

There's more...

WebGL in itself has no built-in support to load a 3D scene defined in a regular 3D file format. The viewer code or a library such as three.dart, which is a port of Three.js (get it from the pub as three is necessary to display a 3D scene). To create content, use a regular content-creation tool and export the content to a viewer-readable format.

See also

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset