Skip to content

Commit

Permalink
Fix numerical instabilities with box filter splatting
Browse files Browse the repository at this point in the history
  • Loading branch information
Speierers committed Oct 3, 2022
1 parent 39ff404 commit 2d89762
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 13 deletions.
5 changes: 4 additions & 1 deletion src/python/python/ad/integrators/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,10 @@ def sample_rays(
# Return a reparameterized image position
pos_f = ds.uv + film.crop_offset()

return ray, weight, pos_f, reparam_det
# With box filter, ignore random offset to prevent numerical instabilities
splatting_pos = mi.Vector2f(pos) if rfilter.is_box_filter() else pos_f

return ray, weight, splatting_pos, reparam_det

def prepare(self,
sensor: mi.Sensor,
Expand Down
6 changes: 3 additions & 3 deletions src/render/imageblock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,8 @@ MI_VARIANT void ImageBlock<Float, Spectrum>::put_block(const ImageBlock *block)
}

MI_VARIANT void ImageBlock<Float, Spectrum>::put(const Point2f &pos,
const Float *values,
Mask active) {
const Float *values,
Mask active) {
ScopedPhase sp(ProfilerPhase::ImageBlockPut);
constexpr bool JIT = dr::is_jit_v<Float>;

Expand Down Expand Up @@ -175,7 +175,7 @@ MI_VARIANT void ImageBlock<Float, Spectrum>::put(const Point2f &pos,
UInt32 index = dr::fmadd(p.y(), m_size.x(), p.x()) * m_channel_count;

// The sample could be out of bounds
active = active && dr::all(p < m_size);
active &= dr::all(p < m_size);

// Accumulate!
if constexpr (!JIT) {
Expand Down
17 changes: 8 additions & 9 deletions src/render/integrator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -251,9 +251,6 @@ SamplingIntegrator<Float, Spectrum>::render(Scene *scene,

pos += film->crop_offset();

// Cast to floating point, random offset is added in \ref render_sample()
Vector2f pos_f = Vector2f(pos);

// Scale factor that will be applied to ray differentials
ScalarFloat diff_scale_factor = dr::rsqrt((ScalarFloat) spp);

Expand All @@ -262,8 +259,8 @@ SamplingIntegrator<Float, Spectrum>::render(Scene *scene,

// Potentially render multiple passes
for (size_t i = 0; i < n_passes; i++) {
render_sample(scene, sensor, sampler, block,
aovs.get(), pos, diff_scale_factor);
render_sample(scene, sensor, sampler, block, aovs.get(), pos,
diff_scale_factor);

if (n_passes > 1) {
sampler->advance(); // Will trigger a kernel launch of size 1
Expand Down Expand Up @@ -340,10 +337,10 @@ MI_VARIANT void SamplingIntegrator<Float, Spectrum>::render_block(const Scene *s
if (dr::any(pos >= block->size()))
continue;

ScalarPoint2f pos_f = ScalarPoint2f(Point2i(pos) + block->offset());
Point2f pos_f = Point2f(Point2i(pos) + block->offset());
for (uint32_t j = 0; j < sample_count && !should_stop(); ++j) {
render_sample(scene, sensor, sampler, block, aovs,
pos_f, diff_scale_factor);
render_sample(scene, sensor, sampler, block, aovs, pos_f,
diff_scale_factor);
sampler->advance();
}
}
Expand Down Expand Up @@ -372,6 +369,7 @@ SamplingIntegrator<Float, Spectrum>::render_sample(const Scene *scene,
Mask active) const {
const Film *film = sensor->film();
const bool has_alpha = has_flag(film->flags(), FilmFlags::Alpha);
const bool box_filter = film->rfilter()->is_box_filter();

ScalarVector2f scale = 1.f / ScalarVector2f(film->crop_size()),
offset = -ScalarVector2f(film->crop_offset()) * scale;
Expand Down Expand Up @@ -430,7 +428,8 @@ SamplingIntegrator<Float, Spectrum>::render_sample(const Scene *scene,
}
}

block->put(sample_pos, aovs, active);
// With box filter, ignore random offset to prevent numerical instabilities
block->put(box_filter ? pos : sample_pos, aovs, active);
}

MI_VARIANT std::pair<Spectrum, typename SamplingIntegrator<Float, Spectrum>::Mask>
Expand Down

0 comments on commit 2d89762

Please sign in to comment.