-
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)