Skip to content

PSIntegrator: fix biased boundary gradients when sample_border is enabled - #1954

Open
fknfilewalker wants to merge 3 commits into
mitsuba-renderer:masterfrom
fknfilewalker:psintegrator-boundary-fixes
Open

PSIntegrator: fix biased boundary gradients when sample_border is enabled#1954
fknfilewalker wants to merge 3 commits into
mitsuba-renderer:masterfrom
fknfilewalker:psintegrator-boundary-fixes

Conversation

@fknfilewalker

@fknfilewalker fknfilewalker commented Sep 8, 2026

Copy link
Copy Markdown
Contributor
  • Fix boundary sample normalization. Splats used 1 / spp, but when the film samples its border the wavefront is prod(crop_size + 2 * border) * spp, overestimating the derivative. Use prod(crop_size) / wavefront_size instead, which reduces to 1 / spp when no border is sampled.
  • Account for the filter border when culling. Silhouette points outside of the crop window were discarded, although the filter reaches border_size pixels beyond it. Widening the frustum test reduces error against finite differences.
  • Splat boundary samples at the right pixel. sample_direction returns ds.uv relative to the crop window, while ImageBlock::put subtracts the block's own offset, so with a non-zero crop_offset the derivatives landed crop_offset pixels away from the edge they belong to. Add the offset back, as the primal render and ptracer already do.
  • My code follows the style guidelines of this project
  • My changes generate no new warnings
  • My code also compiles for cuda_* and llvm_* variants. If you can't test this, please leave below
  • I have commented my code
  • I have made corresponding changes to the documentation
  • I have added tests that prove my fix is effective or that my feature works
  • I cleaned the commit history and removed any "Merge" commits
  • I give permission that the Mitsuba 3 project may redistribute my contributions under the terms of its license

@fknfilewalker
fknfilewalker force-pushed the psintegrator-boundary-fixes branch from 1a3a2d5 to 43d17e9 Compare September 9, 2026 17:06
fknfilewalker and others added 3 commits September 9, 2026 19:08
Boundary splats were scaled by ``1 / spp``, which assumes a wavefront of
``prod(crop_size) * spp``. When the film samples its border, ``prepare()``
launches ``prod(crop_size + 2 * border) * spp`` samples instead, which
overestimates the derivative by 1.56x for a 16x16 film with the default
Gaussian reconstruction filter.

These image blocks are splatted with ``weight = 0`` and hence need an
explicit sample count. Boundary samples are spread over the crop window,
so the correct factor is ``prod(crop_size) / wavefront_size``. It reduces
to ``1 / spp`` if the film does not sample its border.
Silhouette points projecting outside of the crop window were discarded,
although the reconstruction filter reaches ``border_size`` pixels beyond
it and the primal render does account for them. Widen the frustum test
by that amount when the film samples its border.
``Sensor::sample_direction`` returns ``ds.uv`` relative to the crop window,
while ``ImageBlock::put`` subtracts the block's own offset from the position
it is handed. The boundary splats passed ``ds.uv`` straight through, so with
a non-zero ``crop_offset`` the discontinuous derivatives landed
``crop_offset`` pixels away from the edge they belong to. ``sample_rays``
already adds the offset back for the primal render, and ``ptracer`` does the
same for its particle splats.
@fknfilewalker
fknfilewalker force-pushed the psintegrator-boundary-fixes branch from 43d17e9 to b9351f0 Compare September 9, 2026 17:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant