WebGL API description

4 years ago
Tags: webgl 3d

In this post we are going to dive more deeply into the WebGL library methods that are included in the LimeJS WebGL branch. Those methods are used while making the lime.Renderer.WEBGL renderer and are available for developers to create custom WebGL games.

What it is about:

  • Cleaned up workflow. No more multiline inlining shaders.
  • Object oriented API. C style turned into JavaScript style.
  • Complete handling of format conversions. No need to convert something to another format before sending to WebGL.
  • Debugging support. Get error messages for invalid inputs, instead of black screen.
  • Make it easier to work with big models.
  • Math utility helpers
  • Getting out of your way and letting you concentrate on your shaders.

What it’s not about:

  • A simplified or alternative way of making 3D
  • A higher level abstraction layer.
  • You still have to know how OpenGL works. You just have to code less and get your work done quicker.
  • If you need a Closure port of something like three.js of GLGE this is not it.

The API:

lime.webgl.GLController

GLController is front controller object for your 3D Canvas context. You can use controller object for storing data you need persistent for your context. It also provides method for resizing the viewport. Only real reason for this class existence is that we don’t want to modify the context object itself.

Static Methods:

  • GLController.forCanvas(element) - returns GLController instance for Canvas element. Always returns same object for same element.

Methods:

  • getSize() - get current canvas and viewport size.
  • setSize(size) - resize canvas to new values and also resize WebGL viewport to same size.
  • makeProgram() - Return new Program object for the context.
 
1
2
3
4
var glc = lime.webgl.GLController.forCanvas('mycanvas'),
    gl = glc.gl;

glc.setSize(480,320);

lime.webgl.Program

Program connects the shaders to your code. You use it to initialize your shaders, set shaders properties and draw. Program object accepts data in almost any reasonable form and converts between formats if necessary. When you pass in data in wrong format it will let you know about the error and not just quietly fail with black screen.

Methods:

  • setShader(shader) - load in the shaders to be used by the program. Shaders are meant to be written in separate files and included as a template after running them through lime.py with gensoy command.
  • set*(mixed) - set the value for an attribute or uniform defined in shader. Can accept raw numeric data, arrays, typed arrays, buffers, vectors and matrices. The * is the same name that is used in the shader(for example setUModelViewMatrix()).
  • draw(mode,opt_offset,opt_length) - draw through the program. Mode is WebGL drawing mode constant(gl.TRIANGLES,gl.TRIANGLE_STRIP etc). If offset or length is not set it is taken from the minimal buffer size used.
  • drawElements(buffer,mode,opt_offset,opt_length) - draw the program using element array buffer. First element is the buffer that defines the order of indices that is used for drawing the vertices.
  • use() - set current program as active. You don’t have to call it if you use built in setter and draw commands.
 
1
2
3
4
5
6
7
8
9
attribute vec3 VertexPosition;
attribute vec3 VertexNormal;

uniform float LightIntensity;
uniform mat4 ModelViewMatrix

void main(){
    ....
    }

 

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
var program = glc.makeProgram().setShader(mygame.shaders.myshader);

program.setLightIntensity(.9);

var modelview = lime.webgl.M4().identity().translate(0,0,-7);
program.setModelViewMatrix(modelview);

...

program.draw(gl.TRIANGLES);

lime.webgl.Buffer

Buffers are objects for holding and manipulating big amounts of numeric data. Usually data that represents your model. If you have big models it is good idea to put the data in separate files and then include it with goog.require() when needed.

Methods:

  • Buffer(type,opt_data) - constructor. Type is a JSON object that defines the buffers elements structure. If your buffer only consists of 3 axis vertices the type would be “{float:3}”. If it is a mixture of positions, normals and 4 byte colors the type would be “[{float:3},{float:3},{uint8:4}]”.
  • set(data) - Set new data for the buffer. Accepts array or typed array. All elements are converted based on the buffer definition type.
  • setSize(n) - Resize the buffer to hold up to n elements.
  • reset() - Reset current buffer length to 0. Length represents the number of filled elements. Size represents number of memory slots allocated.
  • getNext() - Get reference to the element at the next empty position of the buffer. Returns an array of typed arrays in same format as the type definition. If you modify the returned element new values will be included in the buffer.
  • subBuffer(index) - Return the SubBuffer object for the index defined in buffer type. Note that when you pass a subbuffer into a shader no data is actually cloned but it just chooses correct stride and offset values.
 
1
2
3
4
5
6
7
var teapot = new lime.webgl.Buffer([{float:3},{float:3}],mygame.models.teapot.VERTICES_NORMALS),
    teapot_indices = new lime.webgl.Buffer({uint16:1},mygame.models.teapot.INDICES);

program.setVertexPosition(teapot.subBuffer(0));
program.setVertexNormal(teapot.subBuffer(1));

program.drawElements(teapot_indices,gl.TRIANGLES);

Math functions for vector and matrix calculations

In addition the library provides many vector and matrix helper functions. Their main use is to allow quick setup and modification of transformation matrices.

Common Methods:

  • set(mixed)
  • clone()
  • equals()
  • sum()
  • difference()
  • negate()
  • toArray()
  • save() - Saves a vector/matrix values. Can be restored same way as in Canvas2D spec.
  • restore() - Restores vector/matrix values to previously saved values.

Vector Methods:

  • modulus()
  • normalize()
  • dot(vector)
  • multiply(matrix) - Transform a vector with a 4x4 Matrix.

Matrix Methods:

  • identity()
  • translate(mixed)
  • scale(mixed)
  • rotate(theta, axis)
  • determinant()
  • inverse()
  • multiply(matrix)
  • skew(sx, sy)
  • transpose()

Helper functions:

  • lime.webgl.perspective(fovy, aspect, znear, zfar) - Return perspective projection matrix.
  • lime.webgl.ortho(left, right, bottom, top, znear, zfar) - Return orthogonal projection matrix.
 
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
var mvMatrix = lime.webgl.M4().identity().translate(0,0,-5);

//draw with translation only

mvMatrix.save().scale(1.5,1.5).rotate(Math.PI/2,[0,0,1]);

//translation + scale + rotation

mvMatrix.restore();

// back to translation only

Current WebGL API is not in any way complete and will probably change a lot over time. If you have any questions or suggestions, please let us know.