Precomputed Warp Tables in ShoggothOx

Published:

← Back to Blog


In real-time music visualizers, visual elements must morph, flow, and warp continuously to create the illusion of three-dimensional motion. A simple decay loop blurs pixels outward, but to create complex spirals, zooming feedback trails, or swirling vortices, the engine must perform spatial distortions. Doing this by calculating trigonometric functions for millions of pixels at 60 FPS is computationally prohibitive. ShoggothOx solves this efficiency problem using Translation Tables (also known as warp tables).

What is a Translation Table?

A basic translation table is a precomputed array of integers. For a grid of size W × H, the table contains W × H entries. Each entry i stores the source index of the pixel that should be copied to the destination index i:

dst[i] = src[trans[i]]

By representing spatial functions as a lookup table, applying any warp complexity (no matter how mathematically demanding) requires exactly one array index read per pixel. This reduces the computational cost to an O(N) memory indirection, allowing complex distortions to run with negligible CPU overhead. The mathematics are paid only once at precomputation time.

ShoggothOx uses interpolation and translation tables at different stages. During the CPU feedback simulation, the production engine uses this classic table directly: one integer source index per destination pixel, with no interpolation weights. Afterward, the completed simulation buffer is uploaded as a texture, where the GPU can use bilinear interpolation to smooth display scaling and texture mapping. Display filtering cannot restore subpixel motion that was rounded away earlier by the CPU warp.

How the simulator uses bilinear weights

Ordinary bilinear interpolation is a gather operation. Given a fractional position (x, y), it reads the values at the four surrounding integer positions and computes one value. The four weights describe how close (x, y) is to each corner.

The simulator applies the same coefficients in the opposite direction, an operation often called bilinear splatting. A warp transforms one source pixel to a fractional destination position. The source value is then divided among the four surrounding destination cells. It is not copied four times: the weights sum to one, so a source value of 200 in this example contributes 90 + 30 + 60 + 20 = 200.

Bilinear interpolation gathers four values into one sample A sample at fractional coordinates point two five and point four receives weighted contributions from four surrounding values. GATHER: four values to one sample z01 (30%) z11 (10%) z00 (45%) z10 (15%) sample (0.25, 0.40) z = .45z00 + .15z10 + .30z01 + .10z11
Display filtering asks: what value belongs at this fractional position?
Bilinear splatting divides one value among four cells A source value of two hundred lands at fractional coordinates and contributes ninety, thirty, sixty, and twenty to four destination cells. SPLAT: one value to four cells 60 (30%) 20 (10%) 90 (45%) 30 (15%) source 200 lands at (0.25, 0.40) 90 + 30 + 60 + 20 = 200
The simulator asks: which destination cells receive this warped source value?

Repeating this distribution can soften an image, so it can resemble diffusion. The distinction is that a warp transform determines the direction and proportions; it is not an equal, directionless spread to neighboring cells. The production engine retains the classic one-index-per-destination table described above.

Common Spatial Warp Generators

By defining different displacement fields, we precompute distinct tables to achieve unique movement effects:

Interactive: Warp Table Feedback Loop
Drag on the canvas to draw luminous green particle lines and watch them warp!

Modular Arithmetic & Wrapping

What happens when a warp pushes coordinate points beyond the boundaries of the screen? To prevent index-out-of-bounds crashes and edge artifacts, ShoggothOx uses positive modular arithmetic to wrap coordinates:

x' = ((x + dx) % W + W) % W

This modular wrapping ensures that pixels displaced off the right edge of the screen seamlessly reappear on the left, keeping the feedback loop continuous and avoiding hard borders.

Resolution Adaptation & Stretching

To adapt a table to another internal buffer size, ShoggothOx scales its integer source and destination coordinates with nearest-neighbor mapping. The result is still a table containing one integer source index per destination. This CPU-side table adaptation is separate from the GPU's bilinear filtering of the finished simulation texture. The engine does not currently use the simulator's weighted technique for table stretching or feedback updates.

Historical Context

This technique dates back to 1990s visualizers. Kevin Burfitt's Cthugha (1994) shipped separate generator executables that computed and wrote `.tab` files on the user's hard drive during installation. Subsequent visualizer launches loaded these files directly. This kept the distribution archive small while preserving execution speed on slow MS-DOS systems. ShoggothOx adopts the same mathematical trade-off, verifying that precomputed lookups remain the fastest mechanism for complex feedback loops today.