Concept: Temporal Accumulation


Core Idea

  • Reuse samples from previous frames to increase effective sample count
  • Frame N has 1 spp, but after 64 frames: 64 effective spp
  • Free quality improvement — no extra ray tracing cost

Basic Algorithm

  • Exponential moving average (EMA)
    • accumulated[t] = lerp(accumulated[t-1], current[t], α)
    • α = 1/N where N = number of accumulated frames
    • α = 1.0 → no accumulation (current frame only)
    • α = 0.1 → blend 10% new, 90% old (slow to respond to changes)
  • Running average (exact)
    • accumulated[t] = (accumulated[t-1] * (N-1) + current[t]) / N
    • Exact average of all N frames
    • Problem: N grows unboundedly — old frames from different scene state

Motion Vector Reprojection

  • Camera and objects move between frames
  • Must find where current pixel was in the previous frame
  • Motion vector: mv = current_uv - previous_uv
  • Reprojection: prev_uv = current_uv - motion_vector
  • Sample previous accumulation buffer at prev_uv
  • Bilinear interpolation for sub-pixel accuracy
  • Computing motion vectors
    • For static objects: only camera motion
      • prev_clip = prev_view_proj * world_pos
      • mv = (current_ndc - prev_ndc) / 2 (in UV space)
    • For dynamic objects: object transform also changes
      • Store previous frame’s transform per object
      • prev_world_pos = prev_transform * local_pos

Ghosting


Blend Factor Tuning

  • High blend factor (α = 0.5): responsive but noisy
  • Low blend factor (α = 0.05): smooth but slow to update, ghosting
  • Adaptive blend factor: increase α when rejection detects stale samples
  • Typical: α = 0.1 for stable regions, α = 1.0 for rejected pixels

Variance Estimation

  • Track variance of accumulated samples for denoiser guidance
  • Online variance: var = E[x²] - E[x]²
  • Accumulate both sum and sum_sq over time
  • mean = sum / N, variance = sum_sq/N - mean²
  • Used by SVGF to guide spatial filtering strength