From c81b015ceaa051a506ca9ee210c559d0173c9b12 Mon Sep 17 00:00:00 2001 From: Wenzel Jakob Date: Sun, 29 Jun 2014 20:25:45 +0200 Subject: [PATCH] volpath: correct attenuation for area lights surrounded by a medium Previously, volpath did not correctly compute the attenuation to an area light source when it was embedded inside a participating medium (i.e. referencing it directly). volpath_simple was unaffected. It is unlikely that anybody ran into this problem, since it was in fact not possible to construct such a scene due to an assertion in shape.cpp. --- src/integrators/path/volpath.cpp | 12 +++++++----- src/librender/shape.cpp | 4 ++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/integrators/path/volpath.cpp b/src/integrators/path/volpath.cpp index ec85df18..690e8012 100644 --- a/src/integrators/path/volpath.cpp +++ b/src/integrators/path/volpath.cpp @@ -378,14 +378,16 @@ public: while (true) { surface = scene->rayIntersect(ray, *its); - if (surface && (interactions == maxInteractions || - !(its->getBSDF()->getType() & BSDF::ENull))) - /* Encountered an occluder -- zero transmittance. */ - break; - if (medium) transmittance *= medium->evalTransmittance(Ray(ray, 0, its->t), sampler); + if (surface && (interactions == maxInteractions || + !(its->getBSDF()->getType() & BSDF::ENull) || + its->isEmitter())) { + /* Encountered an occluder / light source */ + break; + } + if (!surface) break; diff --git a/src/librender/shape.cpp b/src/librender/shape.cpp index 6d173a4a..9e8865f8 100644 --- a/src/librender/shape.cpp +++ b/src/librender/shape.cpp @@ -156,13 +156,13 @@ void Shape::addChild(const std::string &name, ConfigurableObject *child) { m_subsurface = static_cast(child); } else if (cClass->derivesFrom(MTS_CLASS(Medium))) { if (name == "interior") { - Assert(m_interiorMedium == NULL); + Assert(m_interiorMedium == NULL || m_interiorMedium == child); if (m_subsurface != NULL) Log(EError, "Shape \"%s\" has both an interior medium " "and a subsurface scattering model -- please choose one or the other!", getName().c_str()); m_interiorMedium = static_cast(child); } else if (name == "exterior") { - Assert(m_exteriorMedium == NULL); + Assert(m_exteriorMedium == NULL || m_exteriorMedium == child); m_exteriorMedium = static_cast(child); if (m_emitter) m_emitter->setMedium(m_exteriorMedium);