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 29, 2020
1 parent b587ecb commit 5836654
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 52 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
98 changes: 51 additions & 47 deletions src/sensors/tests/test_distant.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,22 @@


def dict_sensor(direction=None, target=None, fwidth=1):
if direction is None:
dict_direction = {}
else:
dict_direction = {"direction": direction}
result = {"type": "distant"}

if target is None:
dict_target = {}
else:
dict_target = {"target": target}
if direction:
result["direction"] = direction

dict_film = {
if target:
result["target"] = target

result["film"] = {
"type": "hdrfilm",
"width": fwidth,
"height": 1,
"rfilter": {"type": "box"}
}

return {
"type": "distant",
**dict_direction,
**dict_target,
"film": dict_film,
}
return result


def make_sensor(direction=None, target=None, fwidth=1):
Expand Down Expand Up @@ -177,45 +170,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

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

def dict_scene(radiance=1.0, spp=1):
return {
"type": "scene",
"shape": {
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 5836654

Please sign in to comment.