Class WGLWidget

Direct Known Subclasses:
WCartesian3DChart

public class WGLWidget extends WInteractWidget
GL support class.

The WGLWidget class is an interface to the HTML5 WebGL infrastructure for client-side rendering, and OpenGL for server-side rendering. Its API is based on the WebGL API. To fully understand WebGL, it is recommended to read the WebGL standard in addition to this documentation.

The most recent version of the WebGL specification can be found here: http://www.khronos.org/registry/webgl/specs/latest/1.0/

The goal of the WGLWidget class is to provide a method to render 3D structures in the browser, where rendering and rerendering is normally done at the client side in JavaScript without interaction from the server, in order to obtain a smooth user interaction. Unless the scene requires server-side updates, there is no communication with the server.

The rendering interface resembles to OpenGL ES, the same standard as WebGL is based on. This is a stripped down version of the normal OpenGL as we usually find them on desktops. Many stateful OpenGL features are not present in OpenGL ES: no modelview and camera transformation stacks, no default lighting models, no support for other rendering methods than through VBOs, ... Therefore much existing example code for OpenGL applications and shaders will not work on WebGL without modifications. The 'learning webgl' web site at http://learningwebgl.com/ is a good starting point to get familiar with WebGL.

To use a WGLWidget, you must derive from it and reimplement the painter methods. Usually, you will always need to implement initializeGL() and paintGL(). Optionally, you may choose to implement resizeGL() (if your widget does not have a fixed size), and updateGL(). If you need to modify the painting methods, a repaint is triggered by calling the repaintGL() method. The default behaviour for any of these four painting functions is to do nothing.

The four painter methods (initializeGL(), resizeGL(), paintGL() and updateGL()) all record JavaScript which is sent to the browser. The JavaScript code of paintGL() is cached client-side, and may be executed many times, e.g. to repaint a scene from different viewpoints. The JavaScript code of initializeGL(), resizeGL() and updateGL() are intended for OpenGL state updates, and is therefore only executed once on the client and is then discarded.

There are four painting methods that you may implement in a specialization of this class. The purpose of these functions is to register what JavaScript code has to be executed to render a scene. Through invocations of the WebGL functions documented below, JWt records the JavaScript calls that have to be invoked in the browser.

  • initializeGL(): this function is executed after the GL context has been initialized. It is also executed when the webglcontextrestored signal is fired. You can distinguish between the first initialization and restoration of context using isRestoringContext(). This is the ideal location to compose shader programs, send VBO's to the client, extract uniform and attribute locations, ... Due to the presence of VBO's, this function may generate a large amount of data to the client.
  • resizeGL(): this function is executed whenever the canvas dimensions change. A change in canvas size will require you to invoke the viewport() function again, as well as recalculate the projection matrices (especially when the aspect ratio has changed). The resizeGL() function is therefore the ideal location to set those properties. The resizeGL() function is invoked automatically on every resize, and after the first initializeGL() invocation. Additional invocations may be triggered by calling repaint() with the RESIZE_GL flag.
  • paintGL(): this is the main scene drawing function. Through its execution, JWt records what has to be done to render a scene, and it is executed every time that the scene is to be redrawn. You can use the VBO's and shaders prepared in the initializeGL() phase. Usually, this function sets uniforms and attributes, links attributes to VBO's, applies textures, and draws primitives. You may also create local programs, buffers, ... Remember that this function is executed a lot of times, so every buffer/program created in this function should also be destroyed to avoid memory leaks. This function is transmitted once to the client, and is executed when the scene needs to be redrawn. Redraws may be triggered from mouse events, timer triggers, events on e.g. a video element, or whatever other event. The paintGL() function can be updated through invoking repaintGL() with the PAINT_GL flag.
  • updateGL(): VBO's, programs, uniforms, GL properties, or anything else set during intializeGL() are not necessarily immutable. If you want to change, add, remove or reconfigure those properties, the execution of an updateGL() function can be triggered by invoking repaintGL() with the UPDATE_GL flag. This signals that updateGL() needs to be evaluated - just once. It is possible that the paintGL() function also requires updates as consequence of the changes in the updateGL() function; in this case, you should also set the PAINT_GL flag of repaintGL().

The GL functions are intended to be used exclusively from within the invocation of the four callback functions mentioned above. In order to manually trigger the execution of these function, use the repaintGL().

A WGLWidget must be given a size explicitly, or must be put inside a layout manager that manages its width and height. The behaviour of a WGLWidget that was not given a size is undefined.

Binary buffer transfers

In bufferDatafv(), there is an additional boolean argument where you can indicate that you want the data to be transferred to the client in binary form. A WMemoryResource is created for each of these buffers. If you know all previous resources are not required in the client anymore, you can free memory with the method clearBinaryResources() (the memory is also managed, so this is not neccesary). If you want to manage these resources entirely by yourself, the following method can be used.

Using createAndLoadArrayBuffer(), you can load an array buffer in binary format from an URL. This will cause the client to fetch the given URL, and make the contents of the file available in an WGLWidget.ArrayBuffer, which can then be used by BufferData() to bind them to an OpenGL buffer. This is ideal to load VBO buffers in a faster way, as it avoids converting floats to text strings on the server and then back to floats on the client. You can combine this with the use of WResource (e.g. WMemoryResource) to send an std::vector of vertices to the client. Note that using WGLWidget.ArrayBuffer is not possible when you want a fall-back in the form of server-side rendering.

Client side matrices and vectors.

The WGLWidget provides the WGLWidget.JavaScriptMatrix4x4 class as a mechanism to use client-side modifiable matrices in the render functions. These matrices can be used identically to the 'constant', with the advantage that there is no need to have a roundtrip to the server to redraw the scene when they are changed. As such, they are ideal for mouse-based camera manipulations, timer triggered animations, or object manipulations.

There's also support for client-side modifiable vectors, with WGLWidget.JavaScriptVector.