From 91b9668aa00178350e8948d203a1bb2846577e3d Mon Sep 17 00:00:00 2001 From: Wenzel Jakob Date: Sun, 30 Sep 2012 03:40:18 -0400 Subject: [PATCH] documentation improvements, some subtle gui improvements, revived MEMLT --- doc/main.bib | 14 ++++ src/integrators/mlt/mlt.cpp | 89 ++++++++++++++++++++------ src/integrators/mlt/mlt_proc.cpp | 34 ++++++++-- src/integrators/pssmlt/pssmlt_proc.cpp | 1 + src/libbidir/mut_manifold.cpp | 10 --- src/mtsgui/glwidget.cpp | 20 ++++-- src/mtsgui/mainwindow.cpp | 2 + src/mtsgui/resources/docs.xml | 14 ++-- 8 files changed, 137 insertions(+), 47 deletions(-) diff --git a/doc/main.bib b/doc/main.bib index 74dcc1fc..f2106da1 100644 --- a/doc/main.bib +++ b/doc/main.bib @@ -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} +} + diff --git a/src/integrators/mlt/mlt.cpp b/src/integrators/mlt/mlt.cpp index 60c4adfd..d23325d9 100644 --- a/src/integrators/mlt/mlt.cpp +++ b/src/integrators/mlt/mlt.cpp @@ -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); diff --git a/src/integrators/mlt/mlt_proc.cpp b/src/integrators/mlt/mlt_proc.cpp index e6e01cfe..591aad3f 100644 --- a/src/integrators/mlt/mlt_proc.cpp +++ b/src/integrators/mlt/mlt_proc.cpp @@ -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; itoString() << 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), diff --git a/src/mtsgui/glwidget.cpp b/src/mtsgui/glwidget.cpp index a3679602..e48d2842 100644 --- a/src/mtsgui/glwidget.cpp +++ b/src/mtsgui/glwidget.cpp @@ -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(); diff --git a/src/mtsgui/mainwindow.cpp b/src/mtsgui/mainwindow.cpp index 6570d307..0cc468c2 100644 --- a/src/mtsgui/mainwindow.cpp +++ b/src/mtsgui/mainwindow.cpp @@ -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); diff --git a/src/mtsgui/resources/docs.xml b/src/mtsgui/resources/docs.xml index bba5963a..f8623160 100644 --- a/src/mtsgui/resources/docs.xml +++ b/src/mtsgui/resources/docs.xml @@ -532,13 +532,13 @@ Selectively enable/disable the bidirectional mutation - + Selectively enable/disable the lens perturbation - + Selectively enable/disable the caustic perturbation - + Selectively enable/disable the multi-chain perturbation @@ -592,16 +592,16 @@ Selectively enable/disable the bidirectional mutation - + Selectively enable/disable the lens perturbation - + Selectively enable/disable the caustic perturbation - + Selectively enable/disable the multi-chain perturbation - + Selectively enable/disable the manifold perturbation