From 399d7b2173bbf6e68fc3a46c92e1ca8fd5cbc695 Mon Sep 17 00:00:00 2001 From: Wenzel Jakob Date: Mon, 17 Feb 2014 15:05:17 +0100 Subject: [PATCH] added field integrator; bugfixes --- doc/main.bib | 1 - include/mitsuba/render/imageblock.h | 2 +- src/films/tiledhdrfilm.cpp | 5 +- src/integrators/CMakeLists.txt | 1 + src/integrators/SConscript | 1 + src/integrators/misc/field.cpp | 170 ++++++++++++++++++++++++++ src/integrators/misc/multichannel.cpp | 57 +++++++-- 7 files changed, 222 insertions(+), 15 deletions(-) create mode 100644 src/integrators/misc/field.cpp diff --git a/doc/main.bib b/doc/main.bib index 0744deaf..094f0075 100644 --- a/doc/main.bib +++ b/doc/main.bib @@ -513,7 +513,6 @@ author={Kelemen, C. and Szirmay-Kalos, L. and Antal, G. and Csonka, F.}, booktitle={Computer Graphics Forum}, volume={21}, - number={3}, pages={531--540}, year={2002} } diff --git a/include/mitsuba/render/imageblock.h b/include/mitsuba/render/imageblock.h index 8f43a976..8c389d49 100644 --- a/include/mitsuba/render/imageblock.h +++ b/include/mitsuba/render/imageblock.h @@ -206,7 +206,7 @@ public: /// Create a clone of the entire image block ref clone() const { ref clone = new ImageBlock(m_bitmap->getPixelFormat(), - m_bitmap->getSize() - Vector2i(2*m_borderSize, 2*m_borderSize), m_filter); + m_bitmap->getSize() - Vector2i(2*m_borderSize, 2*m_borderSize), m_filter, m_bitmap->getChannelCount()); copyTo(clone); return clone; } diff --git a/src/films/tiledhdrfilm.cpp b/src/films/tiledhdrfilm.cpp index 4c7227f5..14f67a12 100644 --- a/src/films/tiledhdrfilm.cpp +++ b/src/films/tiledhdrfilm.cpp @@ -264,7 +264,7 @@ public: Imf::ChannelList &channels = header.channels(); for (size_t i=0; igetUInt8Data(); for (size_t i=0; iinsert(m_channelNames[i], + m_frameBuffer->insert(m_channelNames[i].c_str(), Imf::Slice(compType, ptr, m_pixelStride, m_rowStride)); ptr += compStride; } @@ -332,7 +332,6 @@ public: ++m_peakUsage; } - uint32_t idx = (uint32_t) x + (uint32_t) y * m_blocksH; m_origBlocks[idx] = copy1; m_mergedBlocks[idx] = copy2; diff --git a/src/integrators/CMakeLists.txt b/src/integrators/CMakeLists.txt index 937f4570..dc5f61ec 100644 --- a/src/integrators/CMakeLists.txt +++ b/src/integrators/CMakeLists.txt @@ -30,6 +30,7 @@ add_integrator(adaptive misc/adaptive.cpp) add_integrator(irrcache misc/irrcache.cpp misc/irrcache_proc.h misc/irrcache_proc.cpp) add_integrator(multichannel misc/multichannel.cpp) +add_integrator(field misc/field.cpp) # Bidirectional techniques add_bidir(bdpt bdpt/bdpt.h bdpt/bdpt.cpp diff --git a/src/integrators/SConscript b/src/integrators/SConscript index c6ac9679..27eefad8 100644 --- a/src/integrators/SConscript +++ b/src/integrators/SConscript @@ -17,6 +17,7 @@ plugins += env.SharedLibrary('vpl', ['vpl/vpl.cpp']) plugins += env.SharedLibrary('adaptive', ['misc/adaptive.cpp']) plugins += env.SharedLibrary('irrcache', ['misc/irrcache.cpp', 'misc/irrcache_proc.cpp']) plugins += env.SharedLibrary('multichannel', ['misc/multichannel.cpp']) +plugins += env.SharedLibrary('field', ['misc/field.cpp']) # Bidirectional techniques bidirEnv = env.Clone() diff --git a/src/integrators/misc/field.cpp b/src/integrators/misc/field.cpp new file mode 100644 index 00000000..490a89d2 --- /dev/null +++ b/src/integrators/misc/field.cpp @@ -0,0 +1,170 @@ +/* + This file is part of Mitsuba, a physically based rendering system. + + Copyright (c) 2007-2012 by Wenzel Jakob and others. + + Mitsuba is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License Version 3 + as published by the Free Software Foundation. + + Mitsuba is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include +#include + +MTS_NAMESPACE_BEGIN + +/*!\plugin{field}{Field extraction integrator} + * \order{17} + * \parameters{ + * \parameter{field}{\String}{Denotes the name of the field that should be extracted. + * The following choices are possible: + * \begin{itemize} + * \setlength{\itemsep}{1pt} + * \setlength{\parskip}{1pt} + * \item \code{position}: 3D position in world space + * \item \code{relPosition}: 3D position in camera space + * \item \code{distance}: Ray distance to the shading point + * \item \code{geoNormal}: Geometric surface normal + * \item \code{shNormal}: Shading surface normal + * \item \code{uv}: UV coordinate value + * \item \code{shapeIndex}: Integer index of the high-level shape + * \item \code{primIndex}: Integer shape primitive index + * \end{itemize} + * } + * } + * + * This integrator extracts a requested field of from the intersection records of shading + * points and converts the resulting data into color values. It is meant to be used in conjunction with + * \pluginref{multichannel} to dump auxiliary information (such as depth or surface normals + * of surfaces seen by the camera) into extra channels of a rendered image, for instance to + * create benchmark data for computer vision applications. + * Please refer to the documentation of \pluginref{multichannel} for an example. + */ + +class FieldIntegrator : public SamplingIntegrator { +public: + enum EField { + EPosition, + ERelativePosition, + EDistance, + EGeometricNormal, + EShadingNormal, + EUV, + EShapeIndex, + EPrimIndex + }; + + FieldIntegrator(const Properties &props) : SamplingIntegrator(props) { + std::string field = props.getString("field"); + + if (field == "position") { + m_field = EPosition; + } else if (field == "relPosition") { + m_field = ERelativePosition; + } else if (field == "distance") { + m_field = EDistance; + } else if (field == "geoNormal") { + m_field = EGeometricNormal; + } else if (field == "shNormal") { + m_field = EShadingNormal; + } else if (field == "uv") { + m_field = EUV; + } else if (field == "shapeIndex") { + m_field = EShapeIndex; + } else if (field == "primIndex") { + m_field = EPrimIndex; + } else { + Log(EError, "Invalid 'field' parameter. Must be one of 'position', " + "'relPosition', 'distance', 'geoNormal', 'shNormal', " + "'primIndex', 'shapeIndex', or 'uv'!"); + } + + if (SPECTRUM_SAMPLES != 3 && (m_field == EUV || m_field == EShadingNormal || m_field == EGeometricNormal + || m_field == ERelativePosition || m_field == EPosition)) { + Log(EError, "The field integrator implementation requires renderings to be done in RGB when " + "extracting positional data or surface normals / UV coordinates."); + } + } + + FieldIntegrator(Stream *stream, InstanceManager *manager) + : SamplingIntegrator(stream, manager) { + m_field = (EField) stream->readInt(); + } + + void serialize(Stream *stream, InstanceManager *manager) const { + SamplingIntegrator::serialize(stream, manager); + stream->writeInt((int) m_field); + } + + Spectrum Li(const RayDifferential &ray, RadianceQueryRecord &rRec) const { + Spectrum result(0.0f); + + if (!rRec.rayIntersect(ray)) + return Spectrum(0.0f); + + Intersection &its = rRec.its; + + switch (m_field) { + case EPosition: + result.fromLinearRGB(its.p.x, its.p.y, its.p.z); + break; + case ERelativePosition: { + const Sensor *sensor = rRec.scene->getSensor(); + const Transform &t = sensor->getWorldTransform()->eval(its.t).inverse(); + Point p = t(its.p); + result.fromLinearRGB(p.x, p.y, p.z); + } + break; + case EDistance: + result = Spectrum(its.t); + break; + case EGeometricNormal: + result.fromLinearRGB(its.geoFrame.n.x, its.geoFrame.n.y, its.geoFrame.n.z); + break; + case EShadingNormal: + result.fromLinearRGB(its.shFrame.n.x, its.shFrame.n.y, its.shFrame.n.z); + break; + case EUV: + result.fromLinearRGB(its.uv.x, its.uv.y, 0); + break; + case EShapeIndex: { + const ref_vector &shapes = rRec.scene->getShapes(); + result = Spectrum((Float) -1); + for (size_t i=0; i + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * \end{xml} * * \remarks{ * \item Requires the \pluginref{hdrfilm} or \pluginref{tiledhdrfilm}. * \item All nested integrators must * conform to Mitsuba's basic \emph{SamplingIntegrator} interface. - * Currently, only a few of them satisfy this, including: + * Currently, only a few of them do this, including: * \pluginref{field}, \pluginref{ao}, \pluginref{direct}, \pluginref{path}, * \pluginref{volpath}, \pluginref[volpathsimple]{volpath\_simple}, * and \pluginref{irrcache}. @@ -105,7 +140,9 @@ public: ref proc = new BlockedRenderProcess(job, queue, scene->getBlockSize()); - proc->setPixelFormat(Bitmap::EMultiSpectrumAlphaWeight, m_integrators.size() * SPECTRUM_SAMPLES + 2, false); + proc->setPixelFormat( + m_integrators.size() > 1 ? Bitmap::EMultiSpectrumAlphaWeight : Bitmap::ESpectrumAlphaWeight, + m_integrators.size() * SPECTRUM_SAMPLES + 2, false); int integratorResID = sched->registerResource(this); proc->bindResource("integrator", integratorResID);