Concept: Temporal Rejection


Why Rejection is Needed

  • Temporal accumulation assumes previous frame’s sample is valid for current pixel
  • This assumption breaks when:
    • Disocclusion: object moves to reveal previously hidden surface
    • Fast motion: reprojection lands outside the frame or on wrong surface
    • Lighting changes: sudden light on/off
    • Material changes: texture swap, animation
  • Without rejection: ghosting artifacts (stale samples persist)

Depth-Based Rejection

  • Compare depth of reprojected pixel vs expected depth
  • prev_depth = sample(prev_depth_buffer, prev_uv)
  • expected_depth = reproject(current_depth, camera_motion)
  • If |prev_depth - expected_depth| > threshold: reject
  • Threshold: typically 0.1 * current_depth (relative threshold)
  • Catches disocclusion and large depth discontinuities

Normal-Based Rejection

  • Compare surface normals between frames
  • prev_normal = sample(prev_normal_buffer, prev_uv)
  • If dot(current_normal, prev_normal) < threshold: reject
  • Threshold: typically cos(25°) ≈ 0.9
  • Catches surfaces that rotated significantly (e.g., spinning objects)

Color-Based Rejection (Variance Clipping)

  • Clamp previous sample to neighborhood color range
  • Compute mean μ and variance σ² of current pixel’s 3×3 neighborhood
  • Clip previous sample to [μ - k*σ, μ + k*σ] (AABB in color space)
  • k = 1.0 is typical
  • Doesn’t fully reject — blends toward valid range
  • Used in TAA (Temporal Anti-Aliasing) — very effective for ghosting

Velocity-Based Rejection

  • Large motion vectors indicate fast-moving objects
  • If length(motion_vector) > threshold: increase blend factor (more current frame)
  • Doesn’t fully reject but reduces ghosting for fast motion

Disocclusion Detection

  • Most challenging case — no previous sample exists for newly visible pixels
  • Detection: reprojected UV is outside [0,1] range → definitely disoccluded
  • Depth test catches most in-frame disocclusions
  • For remaining cases: use stencil buffer or object ID comparison

Rejection Response

  • Full rejection: α = 1.0 — use only current frame (very noisy)
  • Partial rejection: increase α smoothly based on confidence
  • Confidence map: per-pixel value in [0,1] indicating temporal reliability
  • α = lerp(α_min, 1.0, 1.0 - confidence)