WebGL and glMatrix Extensions for WebSharper Released

Loic Denuziere

Loic Denuziere

Apr 01, 2011

Reading time:

6 mins

Share via:

Today we are happy to announce the release of not one, but two new WebSharper extensions: WebGL and glMatrix. Together, they bring the power of hardware-accelerated 3D into WebSharper.

WebGL

WebGL is a standard by the Khronos Consortium which allows to render hardware-accelerated, plugin-free 3D scenes directly inside web pages. It is gaining strong momentum, with impressive demos like Quake 3 maps or the recent No Comply by Mozilla.

WebGL is an adaptation for JavaScript of the OpenGL ES 2.0 standard. It is supported by the latest versions of Mozilla Firefox and Google Chrome, with more upcoming as Apple (Safari) and Opera are also members of the WebGL Working Group and support it in their beta builds.

The following is a sample program which displays the classic OpenGL hello world, a rotating triangle.

[<JavaScript>]
let RotatingTriangle() =
    let CreateContext (element : Element) =
        let canvas = As<CanvasElement> element.Dom
        canvas.Width <- 300
        canvas.Height <- 300
        ["webgl"; "experimental-webgl"]
        |> List.tryPick (fun s ->
            let gl = As<WebGLRenderingContext> (canvas.GetContext s)
            if gl = null then None else Some gl)

    let vertexSource = "precision highp float;
        attribute vec3 position;
        uniform mat4 perspectiveMatrix;
        uniform mat4 modelViewMatrix;
        void main(void)
        { gl_Position = perspectiveMatrix * modelViewMatrix
                        * vec4(position, 1.0); }"

    let fragmentSource = "precision highp float;
        void main(void) { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); }"

    let canvas = HTML5.Tags.Canvas []
    match CreateContext canvas with
    | None -> JavaScript.Alert "Your browser seems incompatible with WebGL."
    | Some gl ->
        // Create and bind the shader program
        let vertexShader = gl.CreateShader(gl.VERTEX_SHADER)
        gl.ShaderSource(vertexShader, vertexSource)
        gl.CompileShader(vertexShader)
        let fragmentShader = gl.CreateShader(gl.FRAGMENT_SHADER)
        gl.ShaderSource(fragmentShader, fragmentSource)
        gl.CompileShader(fragmentShader)
        let program = gl.CreateProgram()
        gl.AttachShader(program, vertexShader)
        gl.AttachShader(program, fragmentShader)
        gl.LinkProgram(program)
        gl.UseProgram(program)
        // Create and bind the vertex buffer
        let vertexPosition = gl.GetAttribLocation(program, "position")
        gl.EnableVertexAttribArray(vertexPosition)
        let vertexBuffer = gl.CreateBuffer()
        let vertices = Float32Array([| 0.0;  1.0; 0.0;
                                      -1.0; -1.0; 0.0;
                                       1.0; -1.0; 0.0; |])
        gl.BindBuffer(gl.ARRAY_BUFFER, vertexBuffer)
        gl.BufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW)
        gl.VertexAttribPointer(vertexPosition, 3, gl.FLOAT, false, 0, 0)
        // Setup the view matrices
        let perspectiveMatrix = Mat4.Perspective(45., 1., 1., 10000.)
        let uPerspectiveMatrix = gl.GetUniformLocation(program, "perspectiveMatrix")
        gl.UniformMatrix4fv(uPerspectiveMatrix, false, perspectiveMatrix)
        let uModelViewMatrix = gl.GetUniformLocation(program, "modelViewMatrix")
        // Finally, the main loop.
        gl.ClearColor(0., 0., 0., 0.)
        let rec RunFrame (i : int) () =
            let angle = 2. * float i * System.Math.PI / 1000.
            let modelViewMatrix = Mat4.Identity(Mat4.Create())
            Mat4.Translate(modelViewMatrix, [|0.; 0.; -4.|]) |> ignore
            Mat4.RotateY(modelViewMatrix, angle) |> ignore
            gl.UniformMatrix4fv(uModelViewMatrix, false, modelViewMatrix)
            gl.Clear(gl.COLOR_BUFFER_BIT ||| gl.DEPTH_BUFFER_BIT)
            gl.BindBuffer(gl.ARRAY_BUFFER, vertexBuffer)
            gl.DrawArrays(gl.TRIANGLES, 0, 3)
            gl.Flush()
            JavaScript.SetTimeout (RunFrame ((i + 20) % 1000)) 20 |> ignore
        RunFrame 0 ()
    canvas

If you cannot run this example, make sure your browser and your system are compatible and your graphics drivers are up to date. In particular, we found that Firefox blacklists certain system/driver combinations, and Chrome excludes hardware acceleration on Windows XP altogether (this can be overridden by adding the command-line flag "--ignore-gpu-blacklist").

glMatrix

As an adaptation of the embedded version of OpenGL, WebGL doesn't provide matrix operations like translation and rotation, which can make the positioning of 3D objects cumbersome. This is why we also provide an extension for glMatrix. glMatrix is a highly optimized library which provides operations on matrices, vectors and quaternions, greatly facilitating the manipulation of 3D objects. You can see the Mat4 class from glMatrix in use in the above code.

You can retrieve these extensions at the following addresses: WebGL and glMatrix.

Read more from

Can’t find what you were looking for? Drop us a line.

Loic Denuziere
Found a typo?

This blog post is hosted on GitHub here. Feel free to file a ticket or send a PR.

Newsletter

We will not spam you or give your details to anyone.