NeRF's MLP has to be big to memorize fine detail, and a big MLP evaluated millions of times per image is slow. What if the fine detail lived in a lookup table instead, and the MLP itself could stay tiny?
Same idea, two grids. The coarse grid is small enough that every vertex gets its own table slot — dense, one color per chip, no repeats. The fine grid has 16 vertices but only 8 slots: three vertices, spread all over the grid, are forced to share slot 6 (ringed, same color). Instant-NGP just accepts that — it bets that gradient descent can still learn something useful per location, as long as most vertices land somewhere of their own.
Several grids, coarse to fine, each cover the same space; each vertex owns a learned feature. A resolution- grid has vertices — too many to store directly once gets large, so each level keeps a fixed-size hash table of size instead, and a vertex's feature lives at:
Querying a point bilinearly interpolates the 4 surrounding vertices at each level, then concatenates every level's result into one encoding:
- — grid resolution (vertices per axis); — the level's fixed hash table size.
- — a grid vertex's integer coordinates; — bitwise XOR.
- — the query point's fractional position between its 4 surrounding vertices.
- — a corner's bilinear weight; all 4 weights always sum to exactly 1.
- Coarse level: 2² = 4 vertices, table size 4 — dense
Query point sits of the way across, up. Each corner's bilinear weight:
Against features : value .
- Fine level: 4² = 16 vertices, table size 8 — hashed
Same query point, now at in grid units — that's across its cell and up (the fractional part of ). Each corner's weight:
Against hashed features : value .
- Concatenate
The full encoding at this point is — one number per level, handed to the (now tiny) MLP as input.
Drag the query point across the fine grid and watch exactly 4 vertices light up at a time — the bilinear stencil never touches a 5th. Push the point right onto a vertex and one weight goes to 1 while the other 3 vanish: the "interpolation" collapses to a plain lookup.
Two more query points on the fine level:
- q = (0, 0) — exactly on a vertex
All weight () lands on corner , which hashes to slot : value exactly, with zero contribution from the other 3 corners.
- q = (1, 1) — the opposite corner
All weight lands on vertex — the same vertex this chapter's Intuition beat showed colliding into slot 6 with two others. Value , same as whatever else shares that slot.
Drag the query point until the fine level's interpolated feature reaches ≈ 50 (hint: land close to a single vertex — set y to 1 and x near 1/3).
Instant-NGP trades exact per-vertex storage for a fixed memory budget: as resolution climbs, collisions become unavoidable, but the MLP that consumes these features stays small and fast regardless. The next chapter drops the neural network from the picture almost entirely — instead of querying a representation at each ray sample, it stores the scene as an explicit pile of Gaussian blobs you can draw directly.