Skip to content

Commit f583ac9

Browse files
committed
Fixed bugs that led to failing prbvolpath tests, corrected and issue with directional volumetric pdf computation of meshes, and disabled memory heavy test_ad_integrators.py tests on Windows.
1 parent 5cd13c0 commit f583ac9

File tree

4 files changed

+24
-18
lines changed

4 files changed

+24
-18
lines changed

src/integrators/tests/test_ad_integrators.py

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1097,7 +1097,7 @@ def test01_rendering_primal(variants_all_ad_rgb, integrator_name, config):
10971097

10981098

10991099
@pytest.mark.slow
1100-
# @pytest.mark.skipif(os.name == 'nt', reason='Skip those memory heavy tests on Windows')
1100+
@pytest.mark.skipif(os.name == 'nt', reason='Skip those memory heavy tests on Windows')
11011101
@pytest.mark.parametrize('integrator_name, config', CONFIGS)
11021102
def test02_rendering_forward(variants_all_ad_rgb, integrator_name, config):
11031103
if "volpath" in integrator_name and integrator_name != "prbvolpath":
@@ -1153,16 +1153,10 @@ def test02_rendering_forward(variants_all_ad_rgb, integrator_name, config):
11531153
print(f"Success in config: {config.name}, {integrator_name}")
11541154
print(f"-> error mean: {error_mean} (threshold={config.error_mean_threshold})")
11551155
print(f"-> error max: {error_max} (threshold={config.error_max_threshold})")
1156-
# print(f'-> reference image: {pathlib.PurePath(filename)}')
1157-
# filename = join(os.getcwd(), f"test_{integrator_name}_{config.name}_image_fwd.exr")
1158-
# print(f'-> write current image: {pathlib.PurePath(filename)}')
1159-
# mi.util.write_bitmap(filename, image_fwd)
1160-
# filename = join(os.getcwd(), f"test_{integrator_name}_{config.name}_image_error.exr")
1161-
# print(f'-> write error image: {pathlib.PurePath(filename)}')
11621156

11631157

11641158
@pytest.mark.slow
1165-
# @pytest.mark.skipif(os.name == 'nt', reason='Skip those memory heavy tests on Windows')
1159+
@pytest.mark.skipif(os.name == 'nt', reason='Skip those memory heavy tests on Windows')
11661160
@pytest.mark.parametrize('integrator_name, config', CONFIGS)
11671161
def test03_rendering_backward(variants_all_ad_rgb, integrator_name, config):
11681162
if "volpath" in integrator_name and integrator_name != "prbvolpath":
@@ -1217,7 +1211,7 @@ def test03_rendering_backward(variants_all_ad_rgb, integrator_name, config):
12171211

12181212
@pytest.mark.skip
12191213
@pytest.mark.slow
1220-
# @pytest.mark.skipif(os.name == 'nt', reason='Skip those memory heavy tests on Windows')
1214+
@pytest.mark.skipif(os.name == 'nt', reason='Skip those memory heavy tests on Windows')
12211215
def test04_render_custom_op(variants_all_ad_rgb):
12221216
config = DiffuseAlbedoConfig()
12231217
config.initialize()
@@ -1361,11 +1355,14 @@ def test04_render_custom_op(variants_all_ad_rgb):
13611355

13621356
integrator_path = mi.load_dict({
13631357
'type': 'volpath',
1364-
'max_depth': config.integrator_dict['max_depth']
1358+
'max_depth': config.integrator_dict['max_depth'],
1359+
# Use unidirectional sampling for the forward renders, best way to
1360+
# eliminate any bugs in things like Next-Event Estimation
1361+
'sampling_mode': 1
13651362
})
13661363

13671364
# Primal render
1368-
image_ref = integrator_path.render(config.scene, seed=0, spp=args.spp)
1365+
image_ref = integrator_path.render(config.scene, seed=0, spp=args.spp if args.spp > 1e5 else 192000)
13691366

13701367
filename = join(output_dir, f"test_{config.name}_image_primal_ref.exr")
13711368
mi.util.write_bitmap(filename, image_ref)
@@ -1379,7 +1376,7 @@ def test04_render_custom_op(variants_all_ad_rgb):
13791376
theta = mi.Float(fd_step * config.ref_fd_epsilon)
13801377
config.update(theta)
13811378
# Accumulate final image in double precision to avoid truncation error/underflow
1382-
image_1 = mi.TensorXd(integrator_path.render(config.scene, seed=0, spp=args.spp))
1379+
image_1 = mi.TensorXd(integrator_path.render(config.scene, seed=0, spp=args.spp if args.spp > 1e5 else 192000))
13831380
dr.eval(image_1)
13841381
if image_cumulative is not None:
13851382
image_cumulative = image_cumulative + fd_weight * image_1

src/python/python/ad/integrators/prbvolpath.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ def sample(self,
285285
else:
286286
δL += dr.forward_to(Le_surface)
287287

288-
L[active_e_surface_sampl] += dr.detach(Le_surface)
288+
L[active_e_surface_sampl] += dr.detach(Le_surface if is_primal else -Le_surface)
289289

290290
active_surface &= si.is_valid()
291291
bsdf_ctx = mi.BSDFContext()
@@ -335,7 +335,9 @@ def sample(self,
335335
adj_emitted=adj_emitted, adj_throughput=adj_throughput,
336336
δL=δL, mode=mode)
337337

338-
L[active_e] += dr.detach(Lr_dir)
338+
L[active_e] += dr.detach(Lr_dir if is_primal else -Lr_dir)
339+
else:
340+
Lr_dir = mi.Spectrum(0.0)
339341

340342
# -------------------- Phase function sampling ------------------
341343

src/render/mesh.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,6 +1037,7 @@ Mesh<Float, Spectrum>::sample_direction_volume(const Interaction3f &it, const Po
10371037
auto bbox_volume = m_bbox.volume();
10381038
auto bbox_volume_inv_cbrt = dr::rcp(dr::safe_cbrt(bbox_volume));
10391039
dr::masked(near_t, active && (near_t < 0.f)) = 0.0f;
1040+
active &= (far_t > near_t);
10401041
ds.dist = far_t;
10411042
near_t *= bbox_volume_inv_cbrt;
10421043
far_t *= bbox_volume_inv_cbrt;
@@ -1130,6 +1131,7 @@ MI_VARIANT Float Mesh<Float, Spectrum>::pdf_direction_volume(const Interaction3f
11301131
auto bbox_volume = m_bbox.volume();
11311132
auto bbox_volume_inv_cbrt = dr::rcp(dr::safe_cbrt(bbox_volume));
11321133
dr::masked(near_t, active && (near_t < 0.f)) = 0.0f;
1134+
active &= (far_t > near_t);
11331135
near_t *= bbox_volume_inv_cbrt;
11341136
far_t *= bbox_volume_inv_cbrt;
11351137
auto line_pdf = (dr::square(far_t) * far_t - dr::square(near_t) * near_t) / 3.f;

src/render/tests/test_mesh.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1338,12 +1338,13 @@ def test35_mesh_vcalls(variants_vec_rgb):
13381338

13391339
@fresolver_append_path
13401340
def test36_correct_volume(variants_all_rgb):
1341-
objects_to_test = ["obj/cbox_smallbox.obj", "ply/bunny_watertight.ply"]
1341+
# Test that the correct volume is computed for both simple and complex meshes
1342+
objects_to_test = ["tests/obj/cbox_smallbox.obj", "common/meshes/bunny_watertight.ply"]
13421343
object_volumes = [4559445.0373, 1.6012674570083618]
13431344
for mesh_path, mesh_volume in zip(objects_to_test, object_volumes):
13441345
shape = mi.load_dict({
13451346
"type": "obj" if mesh_path.endswith("obj") else "ply",
1346-
"filename": f"resources/data/tests/{mesh_path}",
1347+
"filename": f"resources/data/{mesh_path}",
13471348
})
13481349
assert dr.allclose(shape.volume(), mesh_volume)
13491350

@@ -1380,9 +1381,10 @@ def test37_volume_position_sampling_normalisation(variants_vec_rgb):
13801381
@pytest.mark.slow
13811382
@fresolver_append_path
13821383
def test38_volume_direction_sampling_normalisation(variants_vec_rgb):
1384+
# Test that the directional pdf is normalised
13831385
shape = mi.load_dict({
13841386
"type": "ply",
1385-
"filename": f"resources/data/tests/ply/bunny_watertight.ply",
1387+
"filename": f"resources/data/common/meshes/bunny_watertight.ply",
13861388
})
13871389

13881390
iter_count = 32
@@ -1406,6 +1408,9 @@ def test38_volume_direction_sampling_normalisation(variants_vec_rgb):
14061408

14071409
resulting_line_pdfs = 0.0
14081410

1411+
# We select a set of random points both inside and outside the bounding sphere
1412+
# and then sample the entire sphere of directions. A normalised directional pdf
1413+
# will integrate to 1 over the entire sphere centered at any arbitrary point.
14091414
if iter_index == 0:
14101415
ray_offset = mi.Vector3f(0.0, 0.0, 0.0)
14111416
else:
@@ -1430,7 +1435,7 @@ def test38_volume_direction_sampling_normalisation(variants_vec_rgb):
14301435
test_ds.d = ray.d
14311436

14321437
underlying_pdf = shape.pdf_direction_volume(test_si, test_ds, active)
1433-
resulting_line_pdfs = resulting_line_pdfs + (underlying_pdf / pdf)
1438+
resulting_line_pdfs = resulting_line_pdfs + underlying_pdf * dr.select(pdf != 0.0, dr.rcp(pdf), 0.0)
14341439

14351440
sum_pdf = dr.mean(resulting_line_pdfs / iter_count, axis=None, mode="evaluated")
14361441
assert(dr.allclose(sum_pdf, 1.0, atol=32/(32*131072)**0.5))

0 commit comments

Comments
 (0)