O'Reilly logo

OpenGL Insights by Christophe Riccio, Patrick Cozzi

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

Efficient Text Rendering
in WebGL
Benjamin Encz
13.1 Introduction
As the first plugin-free 3D rendering API for browsers, WebGL is an interesting
technology for the development of web applications. Since it is a low-level graphics
API, the basic functionality is slim, and many features need to be implemented by
the application developer. One of the missing functions is native support for text
rendering. In many applications, especially on the web, text content is an important
factor.
Being a young standard, only a few WebGL applications using text rendering
exist. Furthermore, in contrast to OpenGL, to date, hardly any extensions or libraries
for text rendering are available. Currently we need to implement it on our own. This
chapter introduces and discusses two approaches.
One approach is bitmap fonts, a common technique where single characters are
rendered as textured quads. For WebGL developers, a second approach exists: we can
use the 2D capabilities of the HTML5 element canvas to create textures containing
dynamically rendered text.
This chapter discusses both approaches. It describes each concept, provides
implementation details, and compares the efficiency in different scenarios. De-
mos and documented source code are available on the OpenGL Insights website,
www.openglinsights.com.
183
13
184 II Rendering Techniques
13.2 Canvas-Based Font Rendering
Canvas-based font rendering is a WebGL-specific technique. We can use the HTML5
element canvas to generate a texture font.
13.2.1 The HTML5 Canvas
The canvas element is part of the HTML5 standard. It provides two APIs for graph-
ics. WebGLs functionality is provided by the canvas 3D context. Canvas’ 2D con-
text, in turn, offers an API for drawing 2D raster and vector images, including text.
13.2.2 Concept
When the canvas 2D context is used to draw characters or shapes, the result is pre-
sented on the canvas and stored as a bitmap. This bitmap can be be transformed into
a WebGL texture. Using the 2D context, canvas-based text rendering is implemented
in three steps:
1. Use 2D context to render text onto the canvas,
2. Capture the resulting bitmap as a WebGL texture,
3. Render viewport-aligned triangles shaded with the texture.
Canvas-based text rendering requires two canvas elements: one with a 2D con-
text, to generate the texture, and another with a 3D context, to render the 3D scene,
as shown in Figure 13.1.
Hello World!
(a)
Hello World!
(b)
Figure 13.1. Canvas-based font rendering: (a) texture creation canvas, (b) rendered 3D
scene.
13. Efficient Text Rendering in WebGL 185
13.2.3 Implementation
The first implementation step is to render text using the 2D context as shown in
Listing 13.1. We begin with requesting ctx, the 2D context of the canvas, and
setting up the parameters for our text. Several attributes can be used to vary the
font appearance, including CSS syntax, which allows us to reuse styles from existing
web applications. By calling ctx.fillRect(), we fill the canvas with a blue back-
ground. Then, we call ctx.fillText() to render white text on top. Now, the
image is drawn, and we create a WebGL texture from it, as sho wn in Listing 13.2.
var dynamicImage = document . getElementById(" text");
var ctx = dynamicImage.getContext("2d");
var text = " Hello World ";
var leftOffset = ctx.canvas . width / 2;
var topOffset = ctx.canvas . height / 2;
ctx.fillStyle = "blue ";
ctx. fillRect (0, 0, ctx. canvas .width , c tx . canvas.height );
ctx.fillStyle = "white ";
ctx.lineWidth = 5;
ctx. font = "bold 44px Arial ";
ctx.textAlign = "center ";
ctx.textBaseline = "middle ";
ctx. fillText (text , leftOffset , topOffset);
handleLoadedTexture(dynamicImage);
Listing 13.1. 2D context text rendering.
F irst, we initialize dynamicTexture with the call to gl.createTexture().
Then, we activate flipping for our image, which has an inverted y-axis and would
be displayed upside down otherwise. Next, we copy the content of the 2D context
to the WebGL texture, passing it as the last argument to gl.texImage2D().We
function handleLoadedTexture(image) {
var dynamicTexture = gl.createTexture();
gl . bindTexture(gl.TEXTURE_2D , dynamicTexture);
gl . pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
gl . texImage2D(gl.TEXTURE_2D , 0,gl.LUMINANCE_ALPHA ,gl.LUMINANCE_ALPHA ,gl.
UNSIGNED_BYTE , image);
gl . texParameteri(gl.TEXTURE_2D ,gl.TEXTURE_MIN_FILTER,gl.LINEAR_MIPMAP_LINEAR);
gl . texParameteri(gl.TEXTURE_2D ,gl.TEXTURE_MAG_FILTER,gl.LINEAR );
// Generate the mipmap required for the minimization filter
gl . generateMipmap(gl.TEXTURE_2D);
}
Listing 13.2. Te x t ure c re a t io n .

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

Start Free Trial

No credit card required