#include #include #include "irrproc.h" MTS_NAMESPACE_BEGIN /* Parallel irradiance sampling implementation (worker) */ class IrradianceSamplingWorker : public WorkProcessor { public: IrradianceSamplingWorker(size_t sampleCount, int ssIndex) : m_sampleCount(sampleCount), m_ssIndex(ssIndex) { } IrradianceSamplingWorker(Stream *stream, InstanceManager *manager) { m_sampleCount = (size_t) stream->readLong(); m_ssIndex = stream->readInt(); } void serialize(Stream *stream, InstanceManager *manager) const { stream->writeLong(m_sampleCount); stream->writeInt(m_ssIndex); } ref createWorkUnit() const { return new RangeWorkUnit(); } ref createWorkResult() const { return new IrradianceRecordVector(); } void prepare() { m_scene = static_cast(getResource("scene")); m_integrator = static_cast(m_scene->getIntegrator()); Properties props; props.setLong("sampleCount", m_sampleCount); props.setPluginName("hammersley"); m_sampler = static_cast (PluginManager::getInstance()-> createObject(Sampler::m_theClass, props)); props.setPluginName("independent"); m_independentSampler = static_cast (PluginManager::getInstance()-> createObject(Sampler::m_theClass, props)); m_scene->wakeup(m_resources); const Subsurface *ss = m_scene->getSubsurfaceIntegrators()[m_ssIndex]; m_shapes = ss->getShapes(); for (size_t i=0; igetSurfaceArea()); m_areaPDF.build(); } void process(const WorkUnit *workUnit, WorkResult *workResult, const bool &stop) { const RangeWorkUnit *range = static_cast(workUnit); IrradianceRecordVector *result = static_cast(workResult); const SampleIntegrator *integrator = m_integrator.get(); result->clear(); for (size_t i=range->getRangeStart(); igetRangeEnd(); ++i) { m_sampler->setSampleIndex(i); Point2 sample = m_sampler->next2D(); Float expSamples; unsigned int index = m_areaPDF.sampleReuse(sample.x, expSamples); expSamples *= m_sampleCount; ShapeSamplingRecord sRec; Float pdf = m_shapes[index]->sampleArea(sRec, sample) * expSamples; result->put(IrradianceSample( sRec.p, integrator->E(m_scene.get(), sRec.p, sRec.n, m_independentSampler), 1/pdf )); } } ref clone() const { return new IrradianceSamplingWorker(m_sampleCount, m_ssIndex); } MTS_DECLARE_CLASS() protected: virtual ~IrradianceSamplingWorker() { } private: ref m_scene; ref m_camera; ref m_sampler, m_independentSampler; ref m_integrator; DiscretePDF m_areaPDF; std::vector m_shapes; size_t m_sampleCount; int m_ssIndex; }; void IrradianceRecordVector::load(Stream *stream) { clear(); size_t count = stream->readUInt(); m_samples.resize(count); for (size_t i=0; iwriteUInt((unsigned int) m_samples.size()); for (size_t i=0; i IrradianceSamplingProcess::createWorkProcessor() const { return new IrradianceSamplingWorker(m_sampleCount, m_ssIndex); } ParallelProcess::EStatus IrradianceSamplingProcess::generateWork(WorkUnit *unit, int worker) { if (m_samplesRequested == m_sampleCount) return EFailure; /* Reserve a sequence of at most 'granularity' samples */ size_t workSize = std::min(m_granularity, m_sampleCount - m_samplesRequested); RangeWorkUnit *range = static_cast(unit); range->setRange(m_samplesRequested, m_samplesRequested + workSize - 1); m_samplesRequested += workSize; return ESuccess; } void IrradianceSamplingProcess::processResult(const WorkResult *wr, bool cancelled) { const IrradianceRecordVector *result = static_cast(wr); m_resultMutex->lock(); for (size_t i=0; isize(); ++i) m_samples->put((*result)[i]); m_resultCount += result->size(); m_progress->update(m_resultCount); m_resultMutex->unlock(); } MTS_IMPLEMENT_CLASS(IrradianceRecordVector, false, WorkResult); MTS_IMPLEMENT_CLASS_S(IrradianceSamplingWorker, false, WorkProcessor); MTS_IMPLEMENT_CLASS(IrradianceSamplingProcess, false, ParallelProcess); MTS_NAMESPACE_END