TR – OpenGL Tile Rendering Library
Version 1.3
Copyright (C) 1997-2005 Brian Paul
Introduction
The TR (Tile Rendering) library is an OpenGL utility library for doing tiled rendering. Tiled rendering is a technique for generating large images in pieces (tiles).
TR is memory efficient; arbitrarily large image files may be generated without allocating a full-sized image buffer in main memory.
The TR library is copyrighted by Brian Paul. See the LICENSE file for details.
You may download TR 1.3 from by SHIFT-clicking on one of the following:
• tr-1.3.tar.gz (10Kbytes)
• tr-1.3.zip (10Kbytes)
Prerequisites
TR works with any version of OpenGL or Mesa. No extensions are necessary and there are no dependencies on GLX, WGL or any other window system interface.
TR is written in ANSI C and may be used from C or C++.
The TR demo programs require Mark Kilgard’s GLUT library.
Users should have intermediate experience with OpenGL.
Example
The following image is divided into four rows and three columns of tiles. Note that the image size is not an exact multiple of the tile size. The TR library handles the situation in which the top row and right column are a fraction of the full tile size.
Also note that the tiles do not have to be square.

This is a small example. In reality, one may use tiles of 512 by 512 pixels and the final image may be 4000 by 3000 pixels (or larger!).
Using the Library
Ordinarily, OpenGL can’t render arbitrarily large images. The maximum viewport size is typically 2K pixels or less and the window system usually imposes a maximum color buffer size.
To overcome this limitation we can render large images in pieces (tiles).
To render each tile we must carefully set the viewport and projection matrix and render the entire scene. The TR library hides the details involved in doing this. Also, TR can either automatically assemble the final image or allow the client to write the image, row by row, to a file.
The basic steps in using TR are as follows:
1. Determine where you’ll render the tiles
Tiles may be rendered either in a window (front or back buffer) or in an off-screen buffer. The choice depends on your application. It doesn’t matter to the TR library since TR just retrieves image tiles with glReadPixels. Just be sure glDrawBuffer and glReadBuffer are set to the same buffer.
2. Determine the destination for the final image
The final, large image may either be automatically assembed in main memory by TR or you may elect to process tiles yourself, perhaps writing them to an image file.
3. Isolate your drawing code
It should be a simple matter to completely re-render your OpenGL scene. Ideally, inside the tile rendering loop you should be able to make one function call which clears the color (and depth, etc) buffer(s) and draws your scene. If you’re using a double buffered window you should not call SwapBuffers since glReadBuffer, by default, specifies the back buffer.
4. Allocate a TR context
Every TR function takes a TRcontext pointer. A TR context encapsulates the state of the library and allows one to have several TR contexts simultaneously. TR contexts are allocated with trNew.
5. Set the image and tile sizes
Call trImageSize to set the final image size, in pixels. Optionally, call trTileSize to set the tile size. The default tile size is 256 by 256 pixels with 0 border. Generally, larger tiles are better since fewer tiles (and rendering passes) will be needed.
6. Specify an image or tile buffer
If you want TR to automatically assemble the final image you must call trImageBuffer to specify an image buffer, format, and pixel type. The format and type parameters directly correspond to those used by glReadPixels.
Otherwise, if you want to process image tiles yourself you must call trTileBuffer to specify a tile buffer, format, and pixel type. The trEndTile function will copy the tile image into your buffer. You may then use or write the tile to a file, for example.
7. Optional: set tile rendering order
Since OpenGL specifies that image data are stored in bottom-to-top order TR follows the same model. However, when incrementally writing tiles to a file we usually want to do it in top-to-bottom order since that’s the order used by most file formats.
The trRowOrder function allows you to specify that tiles are to be rendering in TR_TOP_TO_BOTTOM order or TR_BOTTOM_TO_TOP order. The later is the default.
8. Specify the projection
The projection matrix must be carefully controlled by TR in order to produce a final image which has no cracks or edge artifacts.
OpenGL programs typically call glFrustum, glOrtho or gluPerspective to setup the projection matrix. There are three corresponding functions in the TR library. One of them must be called to specify the projection to use. The arguments to the TR projection functions exactly match the arguments to the corresponding OpenGL functions.
9. Tile rendering loop
After the tile size and image size are specified the TR library computes how many tiles will be needed to produce the final image.
The tiles are rendered inside a loop similar to this:
int more = 1;
while (more)
{
trBeginTile(tr);
DrawScene();
more = trEndTile(tr);
}
This should be self-explanatory. Simply call trBeginTile, render your entire scene, and call trEndTile inside a loop until trEndTile returns zero.
10. Query functions
The trGet function can be called to query a number of TR state variables such as the number of rows and columns of tiles, tile size, image size, currently rendered tile, etc. See the detailed description of trGet below.
11. glRasterPos problem
The glRasterPos function is troublesome. The problem is that the current raster position is invalidated if glRasterPos results in a coordinate outside of the window. Subsequent glDrawPixels and glBitmap functions are ignored. This will frequently happen during tiled rendering resulting in flawed images.
TR includes a substitute function: trRasterPos3f which doesn’t have this problem. Basically, replace calls to glRasterPos with trRasterPos. See the included demo programs for example usage.
12. Compilation
Include the tr.h header file in your client code.
Compile and link with the tr.c library source file. There is no need to compile TR as a separate library file.
API Functions
Creating and Destroying Contexts
TRcontext *trNew(void)
Return a pointer to a new TR context and initialize it. Returns NULL if out of memory.
void trDelete(TRcontext *tr)
Deallocate a TR context.
Image and Tile Setup Functions
void trTileSize(TRcontext *tr, GLint width, GLint height, GLint border)
width and height specifies size of tiles to generate. This should be no larger than the size of your window or off-screen image buffer.
border specifies how many pixels along each edge are to be uses as a border.
Borders provide overlap between adjacent tiles and are needed when drawing wide lines (width > 1) or large points (size > 1). The effective tile size is therefore width – 2 * border by height – 2 * border pixels.
void trImageSize(TRcontext *tr, GLint width, GLint height)
Specifies size of final image to generate.
void trTileBuffer(TRcontext *tr, GLenum format, GLenum type, GLvoid *image);
This is an optional function. After a tile is rendered (after trEnd) it will be copied into the buffer specified by this function.
image must point to a buffer large enough to hold an image equal to the tile size specified by trTileSize, minus any border.
format and type are interpreted in the same way as glReadPixels.
void trImageBuffer(TRcontext *tr, GLenum format, GLenum type, GLvoid *image);
This is an optional function. This specifies a buffer into which the final image is assembled.
As tiles are generated they will automatically be copied into this buffer. The image will be complete after the last tile has been rendered.
image must point to a buffer large enough to hold an image equal to the size specified by trImageSize.
format and type are interpreted in the same way as glReadPixels.
Note: trImageBuffer and trTileBuffer are the means by which image data is obtained from the TR library. You must call one (or both) of these functions in order to get output from TR.
void trRowOrder(TRcontext *tr, TRenum order)
Specifies the order in which tiles are generated.
order may take one of two values:
• TR_BOTTOM_TO_TOP – render tiles in bottom to top order (the default)
• TR_TOP_TO_BOTTOM – render tiles in top to bottom order
Projection Setup Functions
void trOrtho(TRcontext *tr, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far)
Specify an orthographic projection as with glOrtho.
Must be called before rendering first tile.
void trFrustum(TRcontext *tr, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far)
Specify a perspective projection as with glFrustum.
Must be called before rendering first tile.
void trPerspective(TRcontext *tr, GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar );
Specify a perspective projection as with gluPerspective.
Must be called before rendering first tile.
Tile Rendering Functions
trBeginTile(TRcontext *tr)
Begin rendering a tile.
int trEndTile(TRcontext *tr)
End rendering a tile.
Return 0 if finished rendering image.
Return 1 if more tiles remain to be rendered.
The trBeginTile and trEndTile functions are meant to be used in a loop like this:
int more = 1;
while (more)
{
trBeginTile(tr);
DrawScene();
more = trEndTile(tr);
}
DrawScene is a function which renders your OpenGL scene. It should include glClear but not SwapBuffers.
Miscellaneous Functions
GLint trGet(TRcontext *tr, TRenum param)
Query TR state. param may be one of the following:
• TR_TILE_WIDTH – returns tile buffer width including border
• TR_TILE_HEIGHT – returns tile buffer height including border
• TR_TILE_BORDER – returns tile border size
• TR_IMAGE_WIDTH – returns image buffer width
• TR_IMAGE_HEIGHT – returns image buffer height
• TR_ROW_ORDER – returns TR_TOP_TO_BOTTOM or TR_BOTTOM_TO_TOP
• TR_ROWS – returns number of rows of tiles in image
• TR_COLUMNS – returns number of columns of tiles in image
• TR_CURRENT_ROW – returns current tile row. The bottom row is row zero.
• TR_CURRENT_COLUMN – returns current tile column The left column is column zero.
• TR_CURRENT_TILE_WIDTH – returns width of current tile
• TR_CURRENT_TILE_HEIGHT – returns height of current tile
Note the difference between TR_TILE_WIDTH/HEIGHT and TR_CURRENT_TILE_WIDTH/HEIGHT. The former is the size of the tile buffer. The later is the size of the current tile which can be less than or equal to the TR_TILE_WIDTH/HEIGHT. Unless the final image size is an exact multiple of the tile size, the last tile in each row and column will be smaller than TR_TILE_WIDTH/HEIGHT.
void trRasterPos3f(TRcontext *tr, GLfloat x, GLfloat y, GLfloat z)
This function is a replacement for glRasterPos3f. The problem with the OpenGL RasterPos functions is that if the resulting window coordinate is outside the view frustum then the raster position is invalidated and glBitmap becomes a no-op.
This function avoids that problem.
You should replace calls to glRasterPos with this function. Otherwise, glRasterPos/glBitmap sequences won’t work correctly during tiled rendering.
Unfortunately, trRasterPos3f can’t be saved in a display list.
Notes
More on Tile Borders
A tile border should be used when drawing any of:
• wide lines (width > 1)
• large points (width > 1)
• antialiased lines or points
• GL_POINT or GL_LINE polygon modes
By using a tile border, rendering artifacts (pixel drop-outs) at tile boundaries can be eliminated.
Suppose you call glTileSize(tr, W, H, B). TR will render tiles of W by H pixels of which B pixels along each edge overlap the adjacent tiles. Therefore, the image buffer specified by calling glTileBuffer() must only be large enough to hold an image of W-2*B by H-2*B pixels.
Demonstration Programs
The TR distribution includes two GLUT-based demo programs:
• trdemo1 – renders a window-size image in tiles
• trdemo2 – produces a large PPM file incrementally
You’ll probably have to edit the Makefile for your computer. Compiling the demos is very simple though since they only require OpenGL and GLUT.
Contributors
• Robin Syllwasschy – provided much helpful feedback for the initial version of TR.
Version History
Version 1.0 – April 1997
• Initial version
Version 1.1 – July 1997
• Added tile border support
• Fixed a few compilation problems
Version 1.2 – December 2003
• Fixed bug in trdemo2.c (Marcel Lancelle)
Version 1.3 – August 2005
• Fixed problem in trdemo1.c using freeglut (initial window size)
• trdemo2.c failed with some NVIDIA cards/drivers because of a glPixelStorei(GL_PACK_ALIGNMENT, 1) call.
Document created on April 19, 1997. Last edited on August 25, 2005.