documentation improvements, some subtle gui improvements, revived MEMLT

metadata
Wenzel Jakob 2012-09-30 03:40:18 -04:00
parent 789312b5e3
commit 91b9668aa0
8 changed files with 137 additions and 47 deletions

View File

@ -515,3 +515,17 @@
pages={531--540},
year={2002}
}
@article{Jakob2012Manifold,
author = {Jakob, Wenzel and Marschner, Steve},
title = {{Manifold Exploration: a Markov Chain Monte Carlo technique for rendering scenes with difficult specular transport}},
journal = {ACM Trans. Graph.},
volume = {31},
number = {4},
month = jul,
year = {2012},
pages = {58:1--58:13},
publisher = {ACM},
address = {New York, NY, USA}
}

View File

@ -40,10 +40,6 @@ MTS_NAMESPACE_BEGIN
* \code{2} will lead to single-bounce (direct-only) illumination,
* and so on. \default{\code{-1}}
* }
* \parameter{rrDepth}{\Integer}{Specifies the minimum path depth, after
* which the implementation will start to use the ``russian roulette''
* path termination criterion. \default{\code{5}}
* }
* \parameter{luminanceSamples}{\Integer}{
* MLT-type algorithms create output images that are only
* \emph{relative}. The algorithm can e.g. determine that a certain pixel
@ -53,23 +49,78 @@ MTS_NAMESPACE_BEGIN
* number of samples. \default{\code{100000} samples}
* }
* \parameter{twoStage}{\Boolean}{Use two-stage MLT?
* See below for details. \default{{\footnotesize\code{false}}}}
* \parameter{bidirectional\showbreak Mutation, [lens,caustic,multiChain]\showbreak Perturbation}{\Boolean}{
* These parameters can be used to choose the mutation strategies that
* should be used. By default, only the bidirectional mutation is
* enabled.
* See \pluginref{pssmlt} for details.\!\default{{\footnotesize\code{false}}}\!}
* \parameter{bidirectional\showbreak\newline Mutation,\vspace{1mm}
* [lens,multiChain,\newline caustic,manifold]\showbreak\newline Perturbation}{\Boolean}{
* These parameters can be used to pick the individual mutation and perturbation
* strategies that will be used to explore path space. By default, the original set
* by Veach and Guibas is enabled (i.e. everything except the manifold
* perturbation). It is possible to extend
* this integrator with additional custom perturbations strategies if needed.
* }
* \parameter{lambda}{\Float}{
* Jump size of the manifold perturbation \default{50}}
* }
* Metropolis Light Transport is a seminal rendering technique proposed by Veach and
* Metropolis Light Transport (MLT) is a seminal rendering technique proposed by Veach and
* Guibas \cite{Veach1997Metropolis}, which applies the Metropolis-Hastings
* algorithm to the problem of light transport in the path-space setting.
*
* algorithm to the path-space formulation of light transport.
* Please refer to the \pluginref{pssmlt} page for a general description of MLT-type
* algorithms and a list of caveats that also apply to this plugin.
*
* Like \pluginref{pssmlt}, this integrator explores the space of light paths,
* searching with preference for those that carry a significant amount of
* energy from an emitter to the sensor. The main difference is that PSSMLT
* does this exploration by piggybacking on another rendering technique and
* ``manipulating'' the random number stream that drives it, whereas MLT does
* not use such an indirection: it operates directly on the actual light
* paths.
*
* This means that the algorithm has access to considerably more
* information about the problem to be solved, which allows it to perform a
* directed exploration of certain classes of light paths. The main downside
* is that the implementation is rather complex, which may make it more
* susceptible to unforeseen problems.
* Mitsuba reproduces the full MLT
* algorithm except for the lens subpath mutation\footnote{In experiments,
* it was not found to produce sigificant convergence improvements and was
* subsequently removed.}. In addition, the plugin also provides the
* manifold perturbation proposed by Jakob and Marschner \cite{Jakob2012Manifold}.
*
* \renderings{
* \vspace{-2mm}
* \includegraphics[width=\textwidth]{images/integrator_mlt_sketch.pdf}\hfill\,
* \vspace{-3mm}
* \caption{The available mutation types}
* }
*
* To explore the space of light paths, MLT iteratively makes changes
* to a light path, which can either be large-scale \emph{mutations} or small-scale
* \emph{perturbations}. Roughly speaking, the \emph{bidirectional mutation} is used
* to jump between different classes of light paths, and each one of the perturbations is
* responsible for efficiently exploring some of these classes.
* All mutation and perturbation strategies can be mixed and matched as
* desired, though for the algorithm to work properly, the bidirectional
* mutation must be active and perturbations should be selected
* as required based on the types of light paths that are present in the
* input scene. The following perturbations are available:
*
* \begin{enumerate}[(a)]
* \item \emph{Lens perturbation}: this perturbation slightly varies the outgoing
* direction at the camera and propagates the resulting ray until it encounters
* the first non-specular object. The perturbation then attempts to create a connection to the
* (unchanged) remainder of the path.
* \item \emph{Caustic perturbation}: essentially a lens perturbation
* that proceeds in the opposite direction.
* \item \emph{Multi-chain perturbation}: used when there are several chains
* of specular interactions, as seen in the swimming pool example above.
* After an initial lens perturbation, a cascade of additional perturbations
* is required until a connection to the (unchanged)
* remainder of the path can finally be established.
* \item \emph{Manifold perturbation}: this perturbation was designed to
* subsume and extend the previous three approaches.
* It creates a perturbation at an arbitrary
* position along the path, proceeding in either direction. Upon encountering
* a chain of specular interactions, it numerically solves for a
* connection path (as opposed to the cascading mechanism employed by the
* multi-chain perturbation).
* \end{enumerate}
*/
class MLT : public Integrator {
public:
@ -130,17 +181,17 @@ public:
m_config.bidirectionalMutation = props.getBoolean("bidirectionalMutation", true);
/* Selectively enable/disable the lens perturbation */
m_config.lensPerturbation = props.getBoolean("lensPerturbation", false);
m_config.lensPerturbation = props.getBoolean("lensPerturbation", true);
/* Selectively enable/disable the caustic perturbation */
m_config.causticPerturbation = props.getBoolean("causticPerturbation", false);
m_config.causticPerturbation = props.getBoolean("causticPerturbation", true);
/* Selectively enable/disable the multi-chain perturbation */
m_config.multiChainPerturbation = props.getBoolean("multiChainPerturbation", false);
m_config.multiChainPerturbation = props.getBoolean("multiChainPerturbation", true);
/* Selectively enable/disable the manifold perturbation */
m_config.manifoldPerturbation = props.getBoolean("manifoldPerturbation", false);
m_config.probFactor = props.getFloat("probFactor", 50);
m_config.probFactor = props.getFloat("probFactor", props.getFloat("lambda", 50));
/* Stop MLT after X seconds -- useful for equal-time comparisons */
m_config.timeout = props.getInteger("timeout", 0);

View File

@ -143,7 +143,8 @@ public:
#endif
for (size_t mutationCtr=0; mutationCtr < m_config.nMutations
&& !stop; ++mutationCtr) {
if (wu->getTimeout() > 0 && (mutationCtr % 8192) == 0 && (int) timer->getMilliseconds() > wu->getTimeout())
if (wu->getTimeout() > 0 && (mutationCtr % 8192) == 0 &&
(int) timer->getMilliseconds() > wu->getTimeout())
break;
/* Query all mutators for their suitability */
@ -203,7 +204,26 @@ public:
suitabilities.normalize();
Float Qyx = mutator->Q(*proposed, *current, muRec.reverse()) * suitabilities[mutatorIdx];
Float a = std::min((Float) 1, Qyx / Qxy);
Float a;
if (!m_config.importanceMap) {
a = std::min((Float) 1, Qyx / Qxy);
} else {
const Float *luminanceValues = m_config.importanceMap->getFloatData();
const Point2 &curPos = current->getSamplePosition();
const Point2 &propPos = proposed->getSamplePosition();
Vector2i size = m_config.importanceMap->getSize();
Point2i curPosI(
std::min(std::max(0, (int) curPos.x), size.x-1),
std::min(std::max(0, (int) curPos.y), size.y-1));
Point2i propPosI(
std::min(std::max(0, (int) propPos.x), size.x-1),
std::min(std::max(0, (int) propPos.y), size.y-1));
Float curValue = luminanceValues[curPosI.x + curPosI.y * size.x];
Float propValue = luminanceValues[propPosI.x + propPosI.y * size.x];
a = std::min((Float) 1, (Qyx * curValue) / (Qxy * propValue));
}
#if defined(MTS_BD_DEBUG_HEAVY)
if (!proposed->verify(m_scene, EImportance, oss)) {
@ -327,8 +347,14 @@ void MLTProcess::develop() {
/* Compute the luminance correction factor */
Float avgLuminance = 0;
for (size_t i=0; i<pixelCount; ++i)
avgLuminance += accum[i].getLuminance();
if (importanceMap) {
for (size_t i=0; i<pixelCount; ++i)
avgLuminance += accum[i].getLuminance() * importanceMap[i];
} else {
for (size_t i=0; i<pixelCount; ++i)
avgLuminance += accum[i].getLuminance();
}
avgLuminance /= (Float) pixelCount;
Float luminanceFactor = m_config.luminance / avgLuminance;

View File

@ -290,6 +290,7 @@ void PSSMLTProcess::develop() {
for (size_t i=0; i<pixelCount; ++i)
avgLuminance += accum[i].getLuminance();
}
avgLuminance /= (Float) pixelCount;
Float luminanceFactor = m_config.luminance / avgLuminance;

View File

@ -239,9 +239,6 @@ bool ManifoldPerturbation::sampleMutation(
}
}
cout << source.toString() << endl;
cout << "a=" << a << ", b=" << b << ", c=" << c << endl;
ETransportMode mode = (step == 1) ? EImportance : ERadiance;
int l = std::min(a, c), m = std::max(a, c);
int q = std::min(b, b+step);
@ -589,13 +586,6 @@ bool ManifoldPerturbation::sampleMutation(
}
}
}
cout << "BEFORE: " << q << endl;
cout << source.vertex(q)->toString() << endl;
cout << " and " << source.vertex(q+1)->toString() << endl;
cout << "AFTER: " << endl;
cout << proposal.vertex(q)->toString() << endl;
cout << " and " << proposal.vertex(q+1)->toString() << endl;
if (!PathVertex::connect(m_scene,
proposal.vertexOrNull(q-1),
proposal.edgeOrNull(q-1),

View File

@ -408,21 +408,27 @@ void GLWidget::timerImpulse() {
}
if (!(m_mouseDrag && m_navigationMode == EStandard) && !m_animation) {
Float moveSpeed = m_context->movementScale
ProjectiveCamera *camera = getProjectiveCamera();
Float delta = m_context->movementScale
* m_clock->getMilliseconds();
if (m_leftKeyDown)
setInverseViewTransform(getInverseViewTransform() *
Transform::translate(Vector(moveSpeed,0,0)));
Transform::translate(Vector(delta,0,0)));
if (m_rightKeyDown)
setInverseViewTransform(getInverseViewTransform() *
Transform::translate(Vector(-moveSpeed,0,0)));
if (m_downKeyDown)
Transform::translate(Vector(-delta,0,0)));
if (m_downKeyDown) {
setInverseViewTransform(getInverseViewTransform() *
Transform::translate(Vector(0,0,-moveSpeed)));
if (m_upKeyDown)
Transform::translate(Vector(0,0,-delta)));
camera->setFocusDistance(camera->getFocusDistance() + delta);
}
if (m_upKeyDown) {
setInverseViewTransform(getInverseViewTransform() *
Transform::translate(Vector(0,0,moveSpeed)));
Transform::translate(Vector(0,0,delta)));
camera->setFocusDistance(camera->getFocusDistance() - delta);
}
}
m_clock->reset();

View File

@ -432,6 +432,8 @@ void MainWindow::on_actionDuplicateTab_triggered() {
currentIndex = m_contextIndex;
SceneContext *currentContext = m_context[currentIndex];
SceneContext *newContext = new SceneContext(currentContext);
if (currentContext->renderJob)
newContext->windowSize -= currentContext->sizeIncrease;
m_contextMutex.lock();
m_context.append(newContext);

View File

@ -532,13 +532,13 @@
<param name="bidirectionalMutation" readableName="Bidirectional mutation" type="boolean" default="true" importance="1">
Selectively enable/disable the bidirectional mutation
</param>
<param name="lensPerturbation" readableName="Lens perturbation" type="boolean" default="false" importance="1">
<param name="lensPerturbation" readableName="Lens perturbation" type="boolean" default="true" importance="1">
Selectively enable/disable the lens perturbation
</param>
<param name="causticPerturbation" readableName="Caustic perturbation" type="boolean" default="false" importance="1">
<param name="causticPerturbation" readableName="Caustic perturbation" type="boolean" default="true" importance="1">
Selectively enable/disable the caustic perturbation
</param>
<param name="multiChainPerturbation" readableName="Multi-chain perturbation" type="boolean" default="false" importance="1">
<param name="multiChainPerturbation" readableName="Multi-chain perturbation" type="boolean" default="true" importance="1">
Selectively enable/disable the multi-chain perturbation
</param>
<param name="manifoldPerturbation" readableName="Manifold perturbation" type="boolean" default="false" importance="1">
@ -592,16 +592,16 @@
<param name="bidirectionalMutation" readableName="Bidirectional mutation" type="boolean" default="false" importance="1">
Selectively enable/disable the bidirectional mutation
</param>
<param name="lensPerturbation" readableName="Lens perturbation" type="boolean" default="false" importance="1">
<param name="lensPerturbation" readableName="Lens perturbation" type="boolean" default="true" importance="1">
Selectively enable/disable the lens perturbation
</param>
<param name="causticPerturbation" readableName="Caustic perturbation" type="boolean" default="false" importance="1">
<param name="causticPerturbation" readableName="Caustic perturbation" type="boolean" default="true" importance="1">
Selectively enable/disable the caustic perturbation
</param>
<param name="multiChainPerturbation" readableName="Multi-chain perturbation" type="boolean" default="false" importance="1">
<param name="multiChainPerturbation" readableName="Multi-chain perturbation" type="boolean" default="true" importance="1">
Selectively enable/disable the multi-chain perturbation
</param>
<param name="manifoldPerturbation" readableName="Manifold perturbation" type="boolean" default="true" importance="1">
<param name="manifoldPerturbation" readableName="Manifold perturbation" type="boolean" default="false" importance="1">
Selectively enable/disable the manifold perturbation
</param>
<param name="probFactor" readableName="Probability factor" type="float" default="50" importance="1">