Skip to content

Commit

Permalink
Distant plugin fix and docs and test updates
Browse files Browse the repository at this point in the history
  • Loading branch information
leroyvn committed May 26, 2020
1 parent b4e6a8a commit 82f1e36
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 37 deletions.
28 changes: 23 additions & 5 deletions src/sensors/distant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,21 @@ Distant directional sensor (:monosp:`distant`)
uniformly over the entire scene.
This sensor plugin implements a distant directional sensor which records
radiation leaving the scene in a given direction. If the ``target`` parameter
is not set, rays cast by the sensor will be distributed uniformly on the cross
section of the scene's bounding sphere.
radiation leaving the scene in a given direction. By default, it records the
(spectral) radiant flux per unit solid angle leaving the scene in the specified
direction (in unit power per unit solid angle). Rays cast by the sensor are
distributed uniformly on the cross section of the scene's bounding sphere.
.. warning::
If this sensor is used with an environment map emitter, it will also record
radiant flux coming from the part of emitter appearing through the scene's
bounding sphere cross section. Care should be taken notably when using the
`constant` or `envmap` emitters.
If the ``target`` parameter is set, the sensor looks at a single point and
records a (spectral) radiant flux per unit surface area per unit solid angle
(in unit power per unit surface area per unit solid angle).
*/

Expand Down Expand Up @@ -116,7 +128,10 @@ MTS_VARIANT class DistantSensor final : public Sensor<Float, Spectrum> {
}

ray.update();
return std::make_pair(ray, wav_weight);
return std::make_pair(
ray, m_has_target
? wav_weight
: wav_weight * (math::Pi<Float> * sqr(m_bsphere.radius)));
}

std::pair<RayDifferential3f, Spectrum> sample_ray_differential(
Expand Down Expand Up @@ -153,7 +168,10 @@ MTS_VARIANT class DistantSensor final : public Sensor<Float, Spectrum> {
ray.has_differentials = false;

ray.update();
return std::make_pair(ray, wav_weight);
return std::make_pair(
ray, m_has_target
? wav_weight
: wav_weight * (math::Pi<Float> * sqr(m_bsphere.radius)));
}

/// This sensor does not occupy any particular region of space, return an
Expand Down
75 changes: 43 additions & 32 deletions src/sensors/tests/test_distant.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,45 +177,56 @@ def test_intersection(variant_scalar_rgb, direction):
ek.dot(direction, [0, 0, -1]), atol=0.1)


@pytest.mark.parametrize("radiance", [10**x for x in range(-3, 4)])
def test_render(variant_scalar_rgb, radiance):
def test_render(variant_scalar_rgb):
# Test render results with a simple scene
from mitsuba.core.xml import load_dict
from mitsuba.core import Bitmap, Struct
from mitsuba.core import Bitmap, Struct, ScalarTransform4f

def dict_scene(radiance=1.0, spp=1):
return {
"type": "scene",
"shape": {
for w_e, w_o in zip(([0, 0, -1], [0, 1, -1]), ([0, 0, -1], [0, 1, -1])):
l_e = 1.0 # Emitted radiance
w_e = list(ek.normalize(w_e)) # Emitter direction
w_o = list(ek.normalize(w_o)) # Sensor direction
cos_theta_e = abs(ek.dot(w_e, [0, 0, 1]))
cos_theta_o = abs(ek.dot(w_o, [0, 0, 1]))

scale = 0.5
rho = 1.0 # Surface reflectance
surface_area = 4. * scale ** 2

expected = l_e * cos_theta_e * surface_area * rho / np.pi * cos_theta_o

dict_scene = {
"type": "scene",
"shape": {
"type": "rectangle",
"bsdf": {"type": "conductor"},
},
"integrator": {"type": "path"},
"sensor": {
"type": "distant",
"film": {
"to_world": ScalarTransform4f.scale(scale),
"bsdf": {"type": "diffuse", "reflectance": rho},
},
"emitter": {
"type": "directional",
"irradiance": l_e,
"direction": w_e
},
"sensor": {
"type": "distant",
"direction": w_o,
"film": {
"type": "hdrfilm",
"width": 1,
"height": 1,
"pixel_format": "rgb",
"width": 1,
"pixel_format": "luminance",
"rfilter": {"type": "box"},
},
"sampler": {
"type": "independent",
"sample_count": spp
},
},
"emitter": {
"type": "constant",
"radiance": {
"type": "spectrum",
"value": radiance
}
}
}

scene = load_dict(dict_scene(spp=1, radiance=radiance))
"sampler": {
"type": "independent",
"sample_count": 512
},
},
"integrator": {"type": "path"}
}

scene = load_dict(dict_scene)
sensor = scene.sensors()[0]
scene.integrator().render(scene, sensor)
img = sensor.film().bitmap()
assert np.allclose(np.array(img), radiance)
img = np.array(sensor.film().bitmap()).squeeze()
assert np.allclose(np.array(img), expected)

0 comments on commit 82f1e36

Please sign in to comment.