diff --git a/src/render/temporal_reference.cpp b/src/render/temporal_reference.cpp index bbc5987..25629fd 100644 --- a/src/render/temporal_reference.cpp +++ b/src/render/temporal_reference.cpp @@ -86,9 +86,11 @@ TemporalReferenceResult temporal_reference_resolve(const TemporalReferenceFrame& if (!previous || !valid_motion(center)) continue; - // Dilate the nearest opaque depth's motion at a silhouette, but - // never resurrect a center pixel with no previous transform. + // Dilate from the nearest compatible depth at a silhouette, but + // never borrow foreground motion for newly exposed background or + // resurrect a center pixel with no previous transform. const TemporalReferencePixel* selected = ¢er; + const float current_depth_tolerance = .002f + .01f * center.depth; const auto min_y = y ? y - 1 : y; const auto min_x = x ? x - 1 : x; const auto max_y = std::min(y + 1, current.height - 1); @@ -96,7 +98,9 @@ TemporalReferenceResult temporal_reference_resolve(const TemporalReferenceFrame& for (auto sy = min_y; sy <= max_y; ++sy) for (auto sx = min_x; sx <= max_x; ++sx) { const auto& candidate = current.pixels[std::size_t(sy) * current.width + sx]; - if (valid_motion(candidate) && candidate.depth < selected->depth) + if (valid_motion(candidate) && + std::abs(candidate.depth - center.depth) <= + current_depth_tolerance && candidate.depth < selected->depth) selected = &candidate; } const float u = (static_cast(x) + .5f) / current.width - selected->motion[0]; diff --git a/tests/render_temporal_reference_tests.cpp b/tests/render_temporal_reference_tests.cpp index 919a9f8..e7009f6 100644 --- a/tests/render_temporal_reference_tests.cpp +++ b/tests/render_temporal_reference_tests.cpp @@ -142,6 +142,12 @@ void nearest_depth_motion_dilation() { prior.depth[4] = .1f; // Undilated center motion would fail this depth check. prior.depth[3] = .2f; prior.color[3] = {.1f, .1f, .1f, 1}; + const auto exposed_background = temporal_reference_resolve(frame, &prior); + require(!exposed_background.accepted[4] && + exposed_background.history.color[4] == frame.pixels[4].color, + "A newly exposed deep background pixel must not borrow foreground motion"); + frame.pixels[4].depth = .203f; + frame.pixels[4].previous_depth = .203f; const auto dilated = temporal_reference_resolve(frame, &prior); require(dilated.accepted[4] && dilated.history.color[4][0] < .5f, "Nearest-depth foreground motion should fill a valid silhouette pixel");