Staying Current With WebGL
Andor Salga | 2 October, 2009 | 23:51
C3DL currently uses the Canvas3D plug-in. If a user wants to see any of our demos run in the browser, they’ll need to install the plug-in. Canvas3D is precursor to WebGL, which was recently added to the Mozilla nightly trunk and will soon be included in a future release of Firefox. Therefore, we need to update our library so demos will run without requiring any plug-ins.
Before I started to update the library, I took another look at Vlad’s spore creature viewer. I noticed he was using VBOs. This is interesting because when I tried using them in C3DL a while ago, I didn’t experience any performance increase I should have. Maybe there was an issue and it was resolved? I’ll come back to VBOs in a later blog.
On my system I have Firefox 3.0.13, 3.5.3 and 3.7a1pre. I’ll be using the two latest versions to get this going. I use the Canvas3D plug-in with 3.5. Firefox 3.7 is endowed with the awesomeness of WebGL, so it should be enough to run some of my local C3DL demos. Theoretically, the only line which needs changing is the line which acquires the rendering context. Unfortunately, you’ll see how that’s not the case.
So I opened up the C3DL rendering file and updated how the library acquires a rendering context:
I got this exception next:
Next one.
The next line wasn’t really a surprise. There are enough changes to the library now that this is expected.
I was pretty excited since I was sure that now I had to be getting a graphics context, but the context should have been colored blue. Was it really working? Something was wrong. I sat thinking about it and thought no rendering was happening because I commented out the swapBuffers() call. It’s probably drawing to the backbuffer and not swapping to the front. I went back to Vlad’s spore creature viewer demo and poked around wondering how he was doing it. I saw there weren’t any call to swapBuffers. The only lines that gave a hint were:
I thought I would then try to set the clear color and do a clear right after I got the graphics context. No other C3DL code would execute in between. I thought it might be worth a try…
I admit, my demo is not quite as impressive as Vlad’s demo, but hey, I have something!
Next, I’ll have to address all those functions which have different signatures and find out what is preventing the framebuffer from being cleared.
Before I started to update the library, I took another look at Vlad’s spore creature viewer. I noticed he was using VBOs. This is interesting because when I tried using them in C3DL a while ago, I didn’t experience any performance increase I should have. Maybe there was an issue and it was resolved? I’ll come back to VBOs in a later blog.
On my system I have Firefox 3.0.13, 3.5.3 and 3.7a1pre. I’ll be using the two latest versions to get this going. I use the Canvas3D plug-in with 3.5. Firefox 3.7 is endowed with the awesomeness of WebGL, so it should be enough to run some of my local C3DL demos. Theoretically, the only line which needs changing is the line which acquires the rendering context. Unfortunately, you’ll see how that’s not the case.
So I opened up the C3DL rendering file and updated how the library acquires a rendering context:
try
{
// Does the user have the Canvas3D plugin?
glCanvas3D = cvs.getContext('moz-glweb20');
}
catch (err)
{
glCanvas3D = null;
}
if(!glCanvas3D)
{
try
{
// Does the user have a browser that supports WebGL?
// If so, use that instead.
glCanvas3D = cvs.getContext('moz-webgl');
}
catch (err)
{
glCanvas3D = null;
}
}
I started Minefield (3.7) and tried to open a demo. I immediately received a C3DL error. This is a bit odd because the conditional below returns true on 3.5 and false on 3.7.
if(effectTemplate instanceof c3dl.EffectTemplate){...}
I decided to make the conditional pass regardless, since I knew for a fact effectTemplate WAS an instaceof c3dl.EffectTemplate. At the same time I thought it would be nice to have a JavaScript debugger in case I need it. Unfortunately, I didn’t find a compatible version of Firebug for 3.7 and I didn’t know how to use Venkman after I had installed it. I was a bit impatient so I just used printf equivalents.
c3dl.debug.logInfo("I'm running");
After forcing the conditional to pass, I tried my code again and got the following error in the Firefox console:
Error: uncaught exception: [Exception... "Not enough arguments [nsICanvasRenderingContextWebGL.uniformMatrix4fv]" nsresult: "0x80570001 (NS_ERROR_XPC_NOT_ENOUGH_ARGS)" location: "JS frame :: file:///Users/andor/Documents/Canvas3D/canvas3dapi/ renderer/rendereropengles20.js :: anonymous :: line 985" data: no]It looked like it was blowing up on this line:
glCanvas3D.uniformMatrix4fv(varLocation, matrix);I checked out the WebGL IDL file and it had the function defined as such:
void uniformMatrix4fv (in GLint location, in GLboolean transpose, in nsICanvasArray value);It seemed some things have been changed since Canvas3D. I only needed to add another parameter, but decided to comment out the line and see what other functions changed.
I got this exception next:
Error: uncaught exception: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsICanvasRenderingContextWebGL. vertexAttribPointer]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: file:///Users/andor/Documents/Canvas3D/canvas3dapi/shaders/ model/standard/std_callback.js :: anonymous :: line 66" data: no]My code:
glCanvas3D.vertexAttribPointer(normalAttribLoc, 3, glCanvas3D.FLOAT, false, 0, currColl.getNormals());No data exists in currColl.getNormals()? I know it still works with 3.5, Commented. Next I got this one:
Error: uncaught exception: [Exception... "Could not convert JavaScript argument arg 1 [nsICanvasRenderingContextWebGL.bindTexture]" nsresult: "0x80570009 (NS_ERROR_XPC_BAD_CONVERT_JS)" location: "JS frame :: file:///Users/andor/Documents/Canvas3D/canvas3dapi/shaders/model/ standard/std_callback.js :: anonymous :: line 110" data: no]It was happening on this line:
glCanvas3D.bindTexture(glCanvas3D.TEXTURE_2D,-1);Here I bind to an invalid texture object in case an object isn’t textured. This prevents the last active texture from being used by this object. Commented.
Next one.
Error: uncaught exception: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsICanvasRenderingContextWebGL. vertexAttribPointer]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: file:///Users/andor/Documents/Canvas3D/canvas3dapi/renderer/ rendereropengles20.js :: anonymous :: line 950" data: no]The code:
this.setVertexAttribArray = function(shader, varName, size, array)
{
let attribLoc = glCanvas3D.getAttribLocation(shader, varName);
if(attribLoc != c3dl.const.SHADER_VAR_NOT_FOUND)
{
// This line is blowing up.
// glCanvas3D.vertexAttribPointer(attribLoc, size, glCanvas3D.FLOAT, false, 0, array);
glCanvas3D.enableVertexAttribArray(attribLoc);
}
else
{
c3dl.debug.logError('Attribute variable "' + varName + '" not found in shader with ID = ' + shader);
}
}
This is a wrapper I wrote to make the C3DL code a bit cleaner, since the third, fourth and fifth parameters always had to be the same. Commented.The next line wasn’t really a surprise. There are enough changes to the library now that this is expected.
No VBO bound to index 0 (or it's been deleted)! Error: uncaught exception: [Exception... "Component returned failure code: 0x80070057 (NS_ERROR_ILLEGAL_VALUE) [nsICanvasRenderingContextWebGL. drawArrays]" nsresult: "0x80070057 (NS_ERROR_ILLEGAL_VALUE)" location: "JS frame :: file:///Users/andor/Documents/Canvas3D/canvas3dapi/ shaders/model/standard/std_callback.js :: anonymous :: line 120" data: no]My line:
glCanvas3D.drawArrays(renderer.getFillMode(), 0, currColl.getVertices(). length/3);Commented, next.
No VBO bound to index 0 (or it's been deleted)! Error: uncaught exception: [Exception... "Component returned failure code: 0x80070057 (NS_ERROR_ILLEGAL_VALUE) [nsICanvasRenderingContextWebGL. drawArrays]" nsresult: "0x80070057 (NS_ERROR_ILLEGAL_VALUE)" location: "JS frame :: file:///Users/andor/Documents/Canvas3D/canvas3dapi/renderer/ rendereropengles20.js :: anonymous :: line 928" data: no]This is because I’m running a mocap demo and I’m rendering points.
glCanvas3D.drawArrays(c3dl.const.FILL,0, (c3dl.const.POINT_VERTICES.length)/3);Again, I commented the line and finally got an interesting one:
Error: glCanvas3D.swapBuffers is not a function Source File: file:///Users/andor/Documents/Canvas3D/canvas3dapi/renderer/ rendereropengles20.js Line: 222I first thought the name might have changed to SwapBuffers (uppercase ‘S’). I looked up the API and saw it was no longer present. This had to be a mistake. I need to tell OpenGL when the backbuffer should be swapped with the front buffer. I commented it and that’s when the errors ceased. I saw the FPS changing on my page, but the context was white. I should have been blue.
I was pretty excited since I was sure that now I had to be getting a graphics context, but the context should have been colored blue. Was it really working? Something was wrong. I sat thinking about it and thought no rendering was happening because I commented out the swapBuffers() call. It’s probably drawing to the backbuffer and not swapping to the front. I went back to Vlad’s spore creature viewer demo and poked around wondering how he was doing it. I saw there weren’t any call to swapBuffers. The only lines that gave a hint were:
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); gl.drawArrays(gl.TRIANGLES, 0, numVertexPoints);He’s clearing the color and depth buffer in one call and drawing what he needs. I couldn’t argue with the code since it was working and mine wasn’t. I was a bit stuck. I turned to my IRC client and pinged joe, mark, dave. Bas and mstange also got involved, trying to help out too. Thanks guys! So I was told that the swapping is probably happening automatically. I decided this is something I can accept since Firefox is now handling the rendering. It uses double buffering to display the content, probably does the same with the canvas. Still, I couldn’t get the canvas to change color.
I thought I would then try to set the clear color and do a clear right after I got the graphics context. No other C3DL code would execute in between. I thought it might be worth a try…
glCanvas3D = cvs.getContext('moz-webgl');
glCanvas3D.clearColor(0,1,0,1);
glCanvas3D.clear(glCanvas3D.COLOR_BUFFER_BIT);
It worked!
I admit, my demo is not quite as impressive as Vlad’s demo, but hey, I have something!Next, I’ll have to address all those functions which have different signatures and find out what is preventing the framebuffer from being cleared.

Wow that sounded incredibly irritating, nevertheless the official inclusion of
Hasan K | 7 October, 2009 | 0:02Wow that sounded incredibly irritating, nevertheless the official inclusion of webGL should be a very interesting time.
I look forward to seeing where this goes!
[...] On 2 October, the developers of C3DL, a Javascript
WebGL around the net, 8 Oct 2009 - Learning WebGL | 8 October, 2009 | 13:04[...] On 2 October, the developers of C3DL, a Javascript library designed to make it easier to write 3D applications for Canvas 3D (the precursor to WebGL on the Mozilla series of browsers) announced that they’re updating their library to WebGL. [...]
[...] my last post, I managed to get our library
Canvas 3d JS Library » WebGL Point Progreess | 12 October, 2009 | 10:45[...] my last post, I managed to get our library to run without crashing using WebGL. After playing with the code a [...]
[...] the conditional evaluated to false. I commented the line
Canvas 3d JS Library » instanceof issues | 18 October, 2009 | 12:00[...] the conditional evaluated to false. I commented the line and I continued working eventually getting something drawn. I did this by added ID’s to most of the C3DL classes. I would then call getObjectType() on [...]