---
kind: concept
slug: level-of-detail-rendering
title: Level-of-detail rendering
summary: >-
  Show far or small content at lower detail so each frame stays affordable. Two cards: a Gaussian-splatting hierarchy with merged parents and blended level switches, and a NeRF with one output head per scale. Results are author-reported on different scenes. Chunked training helps very large captures.
tags: [level-of-detail, real-time-rendering, large-scenes, hierarchy, gaussian-splatting, nerf, multi-scale-rendering, novel-view-synthesis]
papers: ["2112.05504", "2406.12080"]
related: [gaussian-splatting, novel-view-synthesis, neural-radiance-field, positional-encoding, curriculum-learning]
status: draft
updated_at: 2026-11-01
---

## Overview

Level-of-detail (LoD) rendering draws a scene at a resolution that matches how
much of the screen each part covers. Far or small parts are shown at lower
detail, so each frame costs less than drawing the full scene at full detail.
In the hierarchy method, far or small parts are replaced by fewer, coarser
primitives [arxiv:2406.12080 §1, §4.2]. In the progressive NeRF, each detail
level is a separate output of one network [arxiv:2112.05504 §3.3].

The problem it solves is concrete. Radiance fields and 3D Gaussian splatting
keep the whole scene in memory and draw every primitive. Large captures exceed
GPU memory and render too slowly [arxiv:2406.12080 §1]. An LoD scheme addresses
both by drawing only what the current view needs.

The design choices of the hierarchy method, which is the most detailed method
on this page [arxiv:2406.12080 §4, §5, §6]:

1. **Building parents.** Merge a node's children into one primitive whose
   mean, covariance and spherical harmonics are weighted averages of the
   children's [arxiv:2406.12080 §4.1].
2. **Tree shape.** Build a binary tree top-down by median cuts on the longest
   axis of each node's bounding box [arxiv:2406.12080 §4.1].
3. **Pruning.** Remove nodes whose parent adds little detail over its
   children [arxiv:2406.12080 §5.2].
4. **Choosing a cut per view.** Draw a node when its projected size meets a
   pixel target and its parent's does not [arxiv:2406.12080 §4.2].
5. **Switching levels.** Blend each drawn node with its parent over a
   transition, so the switch does not pop [arxiv:2406.12080 §4.2].
6. **Tuning parents.** Optimise interior nodes so they look right when they
   stand in for many children [arxiv:2406.12080 §5.1].
7. **Scaling to very large captures.** Split the scene into chunks, train
   each chunk alone, then consolidate them into one structure
   [arxiv:2406.12080 §6].

The progressive NeRF makes a different set of choices, listed under Variants:
how scales are assigned to images, how each stage adds capacity, and how the
loss treats each output [arxiv:2112.05504 §3.3].

## Variants

Two methods have paper cards here. They solve the same problem with different
representations, so their numbers are not directly comparable.

### Merged Gaussian hierarchy

A tree of 3D Gaussians, cut per view by projected size and blended across
levels. The design choices are items 1 to 7 above. Card:
[Merged-Gaussian tree for multi-km street scenes](/papers/2406.12080).

The paper names Block-NeRF, Mega-NeRF and BungeeNeRF as related large-scene
work and says they do not handle street-level data at this scale
[arxiv:2406.12080 §2]. Its own comparisons are with several splatting and NeRF
baselines on single chunks, and with Mega-NeRF on Mill 19 [arxiv:2406.12080
§8.2]. See Contradictions.

### Progressive multi-scale NeRF

A neural radiance field that gives one output per detail level from one
network. Images are split into four scales by camera distance, one new scale
per 2x zoom-out [arxiv:2112.05504 §3.3]. Training starts with the most distant
scale. Each later stage adds one residual block and one output head. Head L is
supervised by every image whose scale is at most L, so the far views shape
every head and the close views shape only the higher ones [arxiv:2112.05504
§3.3, eq. 3]. Card:
[BungeeNeRF: Progressive Neural Radiance Field for Extreme Multi-scale Scene Rendering](/papers/2112.05504).

The paper's argument is that training one NeRF on all scales at once biases it
towards low frequencies, which blurs close views, and that training each scale
alone leaves seams between scales [arxiv:2112.05504 §3.2, fig. 2]. The card
does not describe a per-view rule for picking a head at render time beyond the
output being one per level.

## When to use which

Each row is a constraint and the choice the cited results support. The
numbers are author-reported.

| Situation | Use | Why |
|---|---|---|
| Scene fits in GPU memory and plain splatting already hits the frame rate | Plain Gaussian splatting, no hierarchy | On one SmallCity chunk, the leaves draw at 58 FPS against 99 FPS for 3DGS [arxiv:2406.12080 tab. 2]. The hierarchy costs about 400 bytes per Gaussian, 69% more than 3DGS [arxiv:2406.12080 §8.2]. |
| Scene larger than GPU memory or too slow to draw in full | Hierarchy, with chunked training | On BigCity, 3DGS reaches 21.48 dB at 72 FPS. The optimised middle cut reaches 23.05 dB at 102 FPS [arxiv:2406.12080 tab. 2]. Consolidated scenes are 6 to 88 GB [arxiv:2406.12080 §8.1]. |
| Interactive frame rate on a large scene, small quality loss acceptable | Optimised cut at the middle pixel target | The middle target averages about 60 FPS across full paths [arxiv:2406.12080 §8.2]. Its PSNR is 0.05 to 0.33 dB below the leaves on the four tab. 2 scenes [arxiv:2406.12080 tab. 2]. |
| Best quality matters more than frame rate | Leaves, or the finest pixel target | The finest target averages 30 FPS or more across full scenes [arxiv:2406.12080 §8.2]. |
| Vehicle or helmet capture with sparse, uneven views | Chunk training with the paper's densification change and depth prior | Averaged over four scenes, the modified densification gives 24.98 dB against 24.43 dB without it. Depth regularisation changes per-image PSNR little (24.98 against 25.10 without it) [arxiv:2406.12080 tab. 6]. The authors describe its benefit as qualitative [arxiv:2406.12080 §8.3]. |
| Tight storage budget | Estimate storage before choosing | The hierarchy stores more per primitive than 3DGS. Theoretical minimum is 284 bytes per Gaussian, implemented is 400 [arxiv:2406.12080 §8.2]. |
| Commercial product with no research-licence exposure | Implement from the paper and check each value | The official code is under a research-only licence, and many values are not stated in the paper [arxiv:2406.12080 §5.1, app. C.1]. |
| One NeRF should give a usable view at several known camera distances, and the scene is a city captured from far to near | Progressive multi-scale NeRF | On 56 Leonard, at the baselines' iteration budget, it averages 23.48 dB against 22.31 dB for Mip-NeRF-full. Trained until convergence it averages 24.51 dB [arxiv:2112.05504 tab. 2]. The paper gives no baseline iteration count, so the same-budget row cannot be matched exactly [arxiv:2112.05504 §4]. |
| Same as above, and the model growing step is kept | Keep the growing schedule | Removing the growing step, with the other parts kept, drops the 56 Leonard average to 22.14 dB. Removing the progressive data feeding drops it to 22.34 dB [arxiv:2112.05504 tab. 3]. |
| Training time or hardware budget must be known in advance | Measure your own budget first | The progressive NeRF uses 100k iterations per stage over four stages [arxiv:2112.05504 §4]. The paper reports no training time or hardware [arxiv:2112.05504 §4], so the cost cannot be compared with the hierarchy's. |
| Public city imagery for a commercial product | Use your own captures, or check the imagery's terms first | The progressive NeRF's scenes are Google Earth Studio imagery, which the paper credits to Google [arxiv:2112.05504 §4]. |

## Implementation sketch

Common core of the hierarchy method: a parent merge, a cut per view, and the
blend weight for one drawn node. Granularity is the projected size of a node's
leaf bounding box, in pixels [arxiv:2406.12080 §4.2]. The ellipsoid surface
used in the merge weight has no formula in the paper [arxiv:2406.12080 §4.1].

```pseudocode
# Merge K children into one parent  [eq. 8] [eq. 3] [eq. 4] [eq. 9]
# Input:  children with mean, cov, sh, opacity
# Output: parent with mean, cov, sh, falloff

def merge(children):
    # Unnormalised weight: opacity times ellipsoid surface  [eq. 8]
    raw = [c.opacity * ellipsoid_surface(c.cov) for c in children]
    total = sum(raw)
    w = [r / total for r in raw]         # normalised, sums to 1
    # Weighted mean, then covariance including child spread  [eq. 3, eq. 4]
    mean = sum(wi * c.mean for wi, c in zip(w, children))
    cov = sum(
        wi * (c.cov + outer(c.mean - mean, c.mean - mean))
        for wi, c in zip(w, children)
    )
    # Weighted SH, same weights  [eq. 9]
    sh = sum(wi * c.sh for wi, c in zip(w, children))
    # Falloff is the unnormalised sum over the parent surface  [§4.1]
    falloff = total / ellipsoid_surface(cov)
    return Gaussian(mean, cov, sh, falloff)
```

```pseudocode
# Choose the cut for one view  [§4.2]
# Input:  tree, camera, pixel target tau
# Output: nodes to draw, each blended with its parent

def select_cut(tree, camera, tau):
    cut = []
    for node in tree.nodes:
        # Node meets the target  [§4.2]
        fine = granularity(node, camera) <= tau
        # Parent is too coarse, or the node is the root  [§4.2]
        coarse_parent = (
            node.parent is None
            or granularity(node.parent, camera) > tau
        )
        if fine and coarse_parent:
            cut.append(node)
    return cut
```

```pseudocode
# Blend weight and child opacity start  [eq. 10] [eq. 12] [§5.2]
# Input:  node, its parent, tau, parent falloff, K children
# Output: weight t, opacity start alpha'

def blend_weight(node, camera, tau):
    # Position of tau between node and parent  [eq. 10]
    # Which end is t = 0 is not stated  [§4.2]
    e_n = granularity(node, camera)
    e_p = granularity(node.parent, camera)
    return (tau - e_n) / (e_p - e_n)

def opacity_start(alpha_parent, k):
    # Start value so the children match the parent's colour  [eq. 12] [§5.2]
    return 1 - (1 - alpha_parent) ** (1 / k)
```

Points to check in an implementation of the hierarchy:

- The falloff clamp, the blend direction and the rotation renormalisation
  are not settled by the paper; see Contradictions and the card's pitfalls
  [arxiv:2406.12080 §4.1, §4.2, §7.3].
- The tree is pruned with a loop over pixel targets, doubling each round
  [arxiv:2406.12080 §5.2]. Which image dimension sets the upper bound is not
  stated.
- Chunk training uses the 3DGS optimiser with a depth prior and per-image
  exposure [arxiv:2406.12080 §6.2, app. C]. The loss for the hierarchy stage
  is not stated [arxiv:2406.12080 §5.1].

The progressive NeRF needs two pieces that are not in the hierarchy: the sum
of residual heads, and the loss that masks rays by scale.

```pseudocode
# Output of head L: base output plus residuals of blocks 2..L  [eq. 2]
# Input:  base output, residual outputs of blocks 2..Lmax, head index L
# Output: colour and density of head L (before rendering)

def head_output(base_out, residuals, L):
    out = base_out
    # residuals[l] is the residual of block l + 2, for colour and density
    for res in residuals[: L - 1]:
        out = out + res
    return out
```

```pseudocode
# Training loss at stage L: each head sees rays up to its scale  [eq. 3] [§3.3]
# Input:  per-head predictions, targets, scale id of each ray, stage L
# Output: scalar loss

def stage_loss(preds, targets, scale_ids, L):
    loss = 0.0
    for l in range(1, L + 1):
        keep = scale_ids <= l        # rays with scale index at most l
        loss += sum_squared_error(preds[l][keep], targets[keep])
    return loss
```

Points to check in an implementation of the progressive NeRF:

- Stage count, the 2x spacing between scales and the number of images per
  scale are set by hand in the authors' code; the paper calls the number of
  scales "relatively flexible" [arxiv:2112.05504 §3.3]. Changing the count
  changes the schedule and the outputs.
- Each stage uses 100k iterations with Adam at learning rate 5e-4, batch 2,048
  rays and a reset optimiser [arxiv:2112.05504 §4]. The paper does not say how
  a new stage's weights are initialised, and the learning-rate decay is
  exponential with no rate given [arxiv:2112.05504 §4].
- The paper's density and colour activations follow the original NeRF
  [arxiv:2112.05504 §3.3]. Where the code's activations sit relative to the
  residual sum is not specified in the paper.

## Contradictions

- **Falloff clamp.** The text says the blended falloff is clamped to 1
  [arxiv:2406.12080 §4.1]. The implementation section says the rasteriser
  clamps the blend at 0.99 and zeroes the opacity gradient when it does
  [arxiv:2406.12080 §7.3]. Both statements come from the same paper. The two
  limits differ only for blended values between 0.99 and 1, and the paper
  does not say which one applies.
- **Street-level scope of the progressive NeRF.** The hierarchy paper says
  Block-NeRF, Mega-NeRF and BungeeNeRF do not handle street-level data at the
  scale it targets [arxiv:2406.12080 §2]. The progressive NeRF paper trains on
  images whose closest scale is at full resolution, and evaluates on city
  scenes captured at a range of camera distances [arxiv:2112.05504 §3.3, §4].
  The progressive NeRF card gives no scene extent in metres or kilometres, so
  the two claims cannot be compared on scale. This page does not resolve it.

## Papers

- [Merged-Gaussian tree for multi-km street scenes (arXiv:2406.12080)](/papers/2406.12080): builds a tree of merged 3D Gaussians for multi-km street scenes, selects a cut by projected size, blends across levels, and consolidates independently trained chunks.
- [BungeeNeRF: Progressive Neural Radiance Field for Extreme Multi-scale Scene Rendering (arXiv:2112.05504)](/papers/2112.05504): trains a NeRF in stages from the most distant scale to the closest, adding one residual block and output head per scale, so one model gives several detail levels.
