Skip to content

Commit

Permalink
Add support for Embree's robust intersection flag
Browse files Browse the repository at this point in the history
  • Loading branch information
dvicini committed Sep 12, 2024
1 parent 40f3119 commit 96e0af2
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 2 deletions.
40 changes: 39 additions & 1 deletion docs/src/plugin_reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,42 @@ Each parameter optionally has flags that are listed in the last column.
These flags indicate whether the parameter is differentiable or not, or whether it introduces
discontinuities and thus needs special treatment.

See :py:class:`mitsuba.ParamFlags` for their documentation.
See :py:class:`mitsuba.ParamFlags` for their documentation.


Scene-wide attributes
---------------------

The Scene object exposes scene-wide attributes. Currently, this functionality is
only used to configure Embree's BVH. In the future, additional settings for the
BVH behavior might be exposed.

**Embree BVH mode:** We expose a scene-level flag to enable Embree's "robust"
mode. Enabling this flag makes Embree use slightly slower but more robust ray
intersection computations. Embree's default "fast" mode can miss ray
intersections when a ray perfectly hits the edge between two adjacent triangles.
Enabling the robust intersection mode fixes that in most cases. Note that Embree
cannot guarantee that all intersections are reported for rays that exactly hit a
vertex, which is a known limitation.

.. pluginparameters::

* - embree_use_robust_intersection
- :paramtype:`bool`
- Whether Embree uses the robust mode flag `RTC_SCENE_FLAG_ROBUST` (Default: |false|).

When creating a scene, the scene-wide attributes can be specified as follows:

.. tabs::
.. code-tab:: xml

<scene version="3.0.0">
<boolean name="embree_use_robust_intersection" value="true"/>
</scene>

.. code-tab:: python

{
'type': 'scene',
'embree_use_robust_intersection': True,
}
3 changes: 2 additions & 1 deletion src/render/scene_embree.inl
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,8 @@ Scene<Float, Spectrum>::accel_init_cpu(const Properties &props) {

s.accel = rtcNewScene(embree_device);
rtcSetSceneBuildQuality(s.accel, RTC_BUILD_QUALITY_HIGH);
rtcSetSceneFlags(s.accel, RTC_SCENE_FLAG_NONE);
bool use_robust = props.get<bool>("embree_use_robust_intersections", false);
rtcSetSceneFlags(s.accel, use_robust ? RTC_SCENE_FLAG_ROBUST : RTC_SCENE_FLAG_NONE);

ScopedPhase phase(ProfilerPhase::InitAccel);
accel_parameters_changed_cpu();
Expand Down
27 changes: 27 additions & 0 deletions src/render/tests/test_scene.py
Original file line number Diff line number Diff line change
Expand Up @@ -315,3 +315,30 @@ def test11_sample_silhouette_bijective(variants_vec_rgb):
out = scene.invert_silhouette_sample(ss)
assert dr.all(ss.discontinuity_type != mi.DiscontinuityFlags.Empty.value)
assert dr.allclose(valid_samples, valid_out, atol=1e-6)


def test_enable_embree_robust_flag(variants_any_llvm):

# We intersect a ray against two adjacent triangles. The ray hits exactly
# the edge between two triangles, which Embree will not count as an
# intersection if the "robust" flag is not set.
R = mi.Transform4f() \
.rotate(dr.normalize(mi.Vector3f(1, 1, 1)), 10) \
.rotate([0, 1, 0], 40)
vertices = mi.Vector3f(
[0.0, 1.0, 0.0, 1.0], [0.0, 0.0, 1.0, 1.0], [0.0, 0.0, 0.0, 0.0])
vertices = R @ vertices

mesh = mi.Mesh("MyMesh", 4, 2)
params = mi.traverse(mesh)
params['vertex_positions'] = dr.ravel(vertices)
params['faces'] = [0, 1, 2, 1, 3, 2]
params.update()
ray = R @ mi.Ray3f(mi.Point3f(0.5, 0.5, 1), mi.Vector3f(0, 0, -1))

scene = mi.load_dict({'type': 'scene', 'mesh': mesh})
assert not scene.ray_intersect(ray).is_valid()

scene = mi.load_dict({'type': 'scene', 'mesh': mesh,
'embree_use_robust_intersections': True})
assert scene.ray_intersect(ray).is_valid()

0 comments on commit 96e0af2

Please sign in to comment.