next up previous contents
Next: 8 Lighting Up: 7 Antialiasing Previous: 7.4 Antialiasing With Textures

7.5 Antialiasing with Accumulation Buffer

Accumulation buffers can be used to antialias a scene without having to depth sort the primitives before rendering. A supersampling technique is used, where the entire scene is offset by small, subpixel amounts in screen space, and accumulated. The jittering can be accomplished by modifying the transforms used to represent the scene.

One straightforward jittering method is to modify the projection matrix, adding small translations in x and y. Care must be taken to compute the translations so that they shift the scene the appropriate amount in window coordinate space. Fortunately, computing these offsets is straightforward. To compute a jitter offset in terms of pixels, divide the jitter amount by the dimension of the object coordinate scene, then multiply by the appropriate viewport dimension. The example code fragment below shows how to calculate a jitter value for an orthographic projection; the results are applied to a translate call to modify the modelview matrix:

void ortho_jitter(GLfloat xoff, GLfloat yoff)
{
	GLint viewport[4];
	GLfloat ortho[16];
	GLfloat scalex, scaley;

	glGetIntegerv(GL_VIEWPORT, viewport);
	/* this assumes that only a glOrtho() call has been
	applied to the projection matrix */
	glGetFloatv(GL_PROJECTION_MATRIX, ortho);

	scalex = (2.f/ortho[0])/viewport[2];
	scaley = (2.f/ortho[5])/viewport[3];
	glTranslatef(xoff * scalex, yoff * scaley, 0.f);
}

If the projection matrix wasn't created by calling glOrtho() or gluOrtho2D(), then you will need to use the viewing volume extents (right, left, top, bottom) to compute scalex and scaley as follows:

        GLfloat right, left, top, bottom;

        scalex = ((right-left)/viewport[2];
        scaley = ((top-bottom)/viewport[3];

The code is very similar for jittering a perspective projection. In this example, we jitter the frustum itself:

void frustum_jitter(GLdouble left, GLdouble right,
				GLdouble bottom, GLdouble top,
				GLdouble near, GLdouble far,
				GLdouble xoff, GLdouble yoff)
{
	GLfloat scalex, scaley;
	GLint viewport[4];

	glGetIntegerv(GL_VIEWPORT, viewport);
	scalex = (right - left)/viewport[2];
	scaley = (top - bottom)/viewport[3];

	glFrustum(left - xoff * scalex,
			right - xoff * scalex,
			top - yoff * scaley,
			bottom - yoff * scaley,
			near, far);
}

The jittering values you choose should fall in an irregular pattern; this reduces aliasing artifacts by making them ``noisy''. Selected subpixel jitter values, organized by the number of samples needed, are taken from the OpenGL Programming Guide, and are shown in Table 2.

  table1212
Table 2: Sample Jittering Values

Using the accumulation buffer, you can easily trade off quality and speed. For higher quality images, simply increase the number of scenes that are accumulated. Although it is simple to antialias the scene using the accumulation buffer, it is much more computationally intensive and probably slower than the polygon antialiasing method described above. Also, OpenGL does not require implementations to support an accumulation buffer, so you may not be able to select a visual or pixel format with an accumulation buffer.


next up previous contents
Next: 8 Lighting Up: 7 Antialiasing Previous: 7.4 Antialiasing With Textures

David Blythe
Thu Jul 17 21:24:28 PDT 1997