Thu 2010-01-07 ( En pr pi )

WebGL has no text rendering functions. But it’s pretty easy to create a texture with text using canvas 2D context:

Looks best in Safari. Firefox has some strange issues with the font rendering.
You need a WebGL-enabled browser to see this.

The interesting code:

// an invisible CANVAS element, 512x512 pixels
<canvas id="textureCanvas" style="display:none" width="512" height="512"></canvas>
var textureCanvas = document.getElementById('textureCanvas')
var ctx = canvas.getContext('2d');

// showcase live rendering by writing the current time
var date = new Date();
function two(number) {
if (number < 10)
return ‘0’ + number;
return number;
var text = two(date.getHours()) + ‘:’ +
two(date.getMinutes()) + ‘:’ +

// let the color of the box rotate every minute
var secs = date.getSeconds() + date.getMilliseconds() / 1000;
ctx.fillStyle = ‘hsl(’ + 360 * (secs / 60) + ‘,100%,50%)’;
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);

// write white text with black border
ctx.fillStyle = ‘white’;
ctx.lineWidth = 2.5;
ctx.strokeStyle = ‘black’;;
ctx.font = ‘bold 80px Verdana’;
ctx.textAlign = ‘center’;
ctx.textBaseline = ‘middle’;
var leftOffset = ctx.canvas.width / 2;
var topOffset = ctx.canvas.height / 2;
ctx.strokeText(text, leftOffset, topOffset);
ctx.fillText(text, leftOffset, topOffset);

// bind our canvas to a 2D texture
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(gl.TEXTURE_2D, 0, textureCanvas);
gl.bindTexture(gl.TEXTURE_2D, null);

Say something! / Sag was!

This is a great example but it doesn't work for me, with webGL enabled. I have tried with 440.0 and 461.0 (ie latest) versions of chromium. 
The console writes: Calling obsolete texImage2D(GLenum target, GLint level, HTMLCanvasElement canvas)

I can't find any notes on this error on the web... :(
Tom @ 04:11 on Friday, 2010-07-09
Yes you're right! I have no idea at the moment, and no time to fix it. Sorry.

It works in Firefox though.
murphy @ 17:13 on Friday, 2010-07-09
Yes, it works for me in firefox too, thanks for the hint. Must be a teething bug with Chrome.
Tom @ 14:18 on Sunday, 2010-07-11
I found the problem, it is simply that Chrome requires the canvas to be a power of 2 rather than 400*400. I made it 512*512 and it works! but 128*64 etc would also work.
Tom @ 02:55 on Friday, 2010-07-16
Thanks, Tom! I fixed it.

I thought I tried this before, because I heard about the power-of-2 issue, but it seems I didn't do it right.
murphy @ 18:18 on Sunday, 2010-07-18
Nice demo but unfortunately it does not work anymore due to changing specs (and implementation of it in the new nightly builds).
What needs to be changed in the source code is this:
1) After <script id="shader-fs" type="x-shader/x-fragment">
  add the following:
  #ifdef GL_ES
  precision highp float;

2) After function handleLoadedTexture(image, texture) {
   add the following:
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);

3) Replace gl.texImage2D(gl.TEXTURE_2D, 0, image);
   with the following:   
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);

4) Replace all instances of WebGLUnsignedShortArray by 

5) Replace all instances of WebGLFloatArray by Float32Array

6) Remark/remove the entire "This code is for Firefox/Minefield compatibility." section

7) The current code does not hide the second cancas which is used to make the clock text. To fix this replace 
  <canvas id="text" style="border: none" width="512" height="512"></canvas>
  <canvas id="text" style="display:none" width="512" height="512"></canvas>

With these modifications, the code works both in the nightly of Firefox (minefield) and Chromium (at least on the versions of 06-oct-2010).
There is only 1 snag which I haven't figured out yet: the clock is mapped in mirror image onto the cube.
Walter @ 11:00 on Sunday, 2010-10-17
Found the reason of the mirror image:

gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
needs to be
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
walter @ 14:40 on Sunday, 2010-10-17
Thanks! I'll fix this when I find the time. Currently busy with preparing for New Zealand holiday :D
murphy @ 01:02 on Wednesday, 2010-10-20
Thanks a lot Walter!
christian @ 19:09 on Monday, 2010-11-29

No markup, just plain monospace text. / Kein Markup, nur Normschrift-Klartext.