mitsuba/src/librender/renderproc.cpp

165 lines
5.1 KiB
C++
Raw Normal View History

/*
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
2011-04-14 21:15:59 +08:00
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 <http://www.gnu.org/licenses/>.
*/
#include <mitsuba/core/statistics.h>
#include <mitsuba/core/sfcurve.h>
#include <mitsuba/render/renderproc.h>
#include <mitsuba/render/rectwu.h>
MTS_NAMESPACE_BEGIN
class BlockRenderer : public WorkProcessor {
public:
BlockRenderer(int blockSize, int borderSize)
: m_blockSize(blockSize), m_borderSize(borderSize) { }
BlockRenderer(Stream *stream, InstanceManager *manager) {
m_blockSize = stream->readInt();
m_borderSize = stream->readInt();
}
ref<WorkUnit> createWorkUnit() const {
return new RectangularWorkUnit();
}
ref<WorkResult> createWorkResult() const {
return new ImageBlock(Bitmap::ESpectrumAlphaWeight,
Vector2i(m_blockSize),
m_sensor->getFilm()->getReconstructionFilter());
}
void prepare() {
Scene *scene = static_cast<Scene *>(getResource("scene"));
m_scene = new Scene(scene);
/// Variance estimates are required when executing a T-test on the rendered data
m_sampler = static_cast<Sampler *>(getResource("sampler"));
m_sensor = static_cast<Sensor *>(getResource("sensor"));
m_integrator = static_cast<SamplingIntegrator *>(getResource("integrator"));
m_scene->removeSensor(scene->getSensor());
m_scene->addSensor(m_sensor);
m_scene->setSensor(m_sensor);
m_scene->setSampler(m_sampler);
m_scene->setIntegrator(m_integrator);
m_integrator->wakeup(m_scene, m_resources);
m_scene->wakeup(m_scene, m_resources);
m_scene->initializeBidirectional();
}
void process(const WorkUnit *workUnit, WorkResult *workResult,
const bool &stop) {
const RectangularWorkUnit *rect = static_cast<const RectangularWorkUnit *>(workUnit);
ImageBlock *block = static_cast<ImageBlock *>(workResult);
#ifdef MTS_DEBUG_FP
2010-12-01 07:46:06 +08:00
enableFPExceptions();
#endif
block->setOffset(rect->getOffset());
block->setSize(rect->getSize());
m_hilbertCurve.initialize(TVector2<uint8_t>(rect->getSize()));
m_integrator->renderBlock(m_scene, m_sensor, m_sampler,
block, stop, m_hilbertCurve.getPoints());
#ifdef MTS_DEBUG_FP
2010-12-01 07:46:06 +08:00
disableFPExceptions();
#endif
}
void serialize(Stream *stream, InstanceManager *manager) const {
stream->writeInt(m_blockSize);
stream->writeInt(m_borderSize);
}
ref<WorkProcessor> clone() const {
return new BlockRenderer(m_blockSize, m_borderSize);
}
MTS_DECLARE_CLASS()
protected:
virtual ~BlockRenderer() { }
private:
ref<Scene> m_scene;
ref<Sensor> m_sensor;
ref<Sampler> m_sampler;
ref<SamplingIntegrator> m_integrator;
int m_blockSize;
int m_borderSize;
HilbertCurve2D<uint8_t> m_hilbertCurve;
};
BlockedRenderProcess::BlockedRenderProcess(const RenderJob *parent, RenderQueue *queue,
int blockSize) : m_queue(queue), m_parent(parent), m_resultCount(0), m_progress(NULL) {
m_blockSize = blockSize;
m_resultMutex = new Mutex();
}
BlockedRenderProcess::~BlockedRenderProcess() {
if (m_progress)
delete m_progress;
}
ref<WorkProcessor> BlockedRenderProcess::createWorkProcessor() const {
return new BlockRenderer(m_blockSize, m_borderSize);
}
void BlockedRenderProcess::processResult(const WorkResult *result, bool cancelled) {
const ImageBlock *block = static_cast<const ImageBlock *>(result);
UniqueLock lock(m_resultMutex);
m_film->put(block);
m_progress->update(++m_resultCount);
lock.unlock();
m_queue->signalWorkEnd(m_parent, block);
}
ParallelProcess::EStatus BlockedRenderProcess::generateWork(WorkUnit *unit, int worker) {
EStatus status = BlockedImageProcess::generateWork(unit, worker);
if (status == ESuccess)
m_queue->signalWorkBegin(m_parent, static_cast<RectangularWorkUnit *>(unit), worker);
return status;
}
void BlockedRenderProcess::bindResource(const std::string &name, int id) {
if (name == "sensor") {
m_film = static_cast<Sensor *>(Scheduler::getInstance()->getResource(id))->getFilm();
m_borderSize = m_film->getReconstructionFilter()->getBorderSize();
Point2i offset = Point2i(0, 0);
Vector2i size = m_film->getCropSize();
if (m_film->hasHighQualityEdges()) {
offset.x -= m_borderSize;
offset.y -= m_borderSize;
size.x += 2 * m_borderSize;
size.y += 2 * m_borderSize;
}
if (m_blockSize < m_borderSize)
Log(EError, "The block size must be larger than the image reconstruction filter radius!");
BlockedImageProcess::init(offset, size, m_blockSize);
if (m_progress)
delete m_progress;
m_progress = new ProgressReporter("Rendering", m_numBlocksTotal, m_parent);
}
BlockedImageProcess::bindResource(name, id);
}
MTS_IMPLEMENT_CLASS(BlockedRenderProcess, false, BlockedImageProcess)
MTS_IMPLEMENT_CLASS_S(BlockRenderer, false, WorkProcessor)
MTS_NAMESPACE_END