Brink is a first-person shooter developed by Splash Damage (where I worked as a graphics programmer). Technically it is quite interesting because it shipped with a number of advanced rendering techniques that were not common in games at the time. This is a forensic look at some of those techniques.
Virtual Texturing
Brink ships with a virtual texturing system — one of the first commercial games to do so. Virtual texturing (also called megatexturing or sparse virtual textures) allows the game to use textures much larger than what fits in GPU memory by streaming only the required tiles.
How It Works in Brink
The implementation follows the classic virtual texturing pipeline:
- Feedback pass — a low-resolution render to determine which tiles are currently needed.
- Tile upload — required tiles (in DXT compressed format) are uploaded to a tile cache texture on the GPU.
- Resolve pass — the page table texture is updated.
- Main render — shaders sample the physical tile cache via an indirection texture (the page table).
Tile Cache and DXT
Tiles are stored in DXT1/DXT5 format in the cache — a 2048×2048 texture split into 128×128 pixel tiles. DXT compression is important because uploading uncompressed tiles would saturate the PCIe bus. With DXT, each tile upload is ~8–32KB which is easily manageable.
32k Textures
With virtual texturing the game can use per-level "world textures" at resolutions up to 32768×32768 pixels. This lets artists paint unique textures across entire levels without repeating patterns — the artists working on Brink made heavy use of this.
Character Customization — Dynamic Texture Composition
One of Brink's marquee features was a deep character customisation system ("SMART" body system). From a technical standpoint this required compositing multiple texture layers per character at runtime.
The system layers clothing, decals, worn/damage overlays, and team colours onto a single composited texture. This is done on GPU via a series of full-screen blit passes, blending each layer into the result. The final composited texture is cached so the composition only needs to re-run when the character's appearance changes.
Lighting — Deferred Shading
Brink uses a deferred shading pipeline. In deferred shading the geometry pass outputs material properties (albedo, normals, specular) into a G-buffer. A subsequent lighting pass reads the G-buffer and evaluates lighting. This decouples the cost of lighting from scene geometry complexity.
The G-buffer layout in Brink uses:
- RT0: Albedo (RGB) + specular intensity (A)
- RT1: World-space normals (encoded)
- RT2: Specular power + other material properties
The deferred approach made it practical to have many dynamic lights in scenes without the multi-pass forward rendering cost.
Forensic Console Commands
Some useful console commands for technical investigation (these work in Brink's id Tech 4 / modified Quake engine base):
r_showTileCache 1 // Visualise the VT tile cache
r_showPageTable 1 // Show the indirection texture
r_showGBuffer 1 // Show the deferred G-buffer channels
r_showFeedback 1 // Show the VT feedback render
These allowed me to capture the screenshots used in this article.