Spectrum SampleIntegrator::E(const Scene *scene, const Point &p, const Normal &n, Float time, const Medium *medium, Sampler *sampler, int nSamples, bool handleIndirect) const { Spectrum E(0.0f); LuminaireSamplingRecord lRec; RadianceQueryRecord rRec(scene, sampler); Frame frame(n); sampler->generate(); for (int i=0; i<nSamples; i++) { rRec.newQuery(RadianceQueryRecord::ERadianceNoEmission, medium); /* Direct */ if (scene->sampleAttenuatedLuminaire(p, time, medium, lRec, rRec.nextSample2D())) { Float dp = dot(lRec.d, n); if (dp < 0) E -= lRec.value * dp; } /* Indirect */ if (handleIndirect) { Vector d = frame.toWorld(squareToHemispherePSA(rRec.nextSample2D())); ++rRec.depth; E += Li(RayDifferential(p, d, time), rRec) * M_PI; } sampler->advance(); } return E / (Float) nSamples; }
Spectrum E(const Scene *scene, const Intersection &its, const Medium *medium, Sampler *sampler, int nSamples, bool handleIndirect) const { Spectrum EDir(0.0f), EIndir(0.0f); DirectSamplingRecord dRec(its); /* Sample the direct illumination component */ for (int i=0; i<nSamples; i++) { int maxIntermediateInteractions = -1; Spectrum directRadiance = scene->sampleAttenuatedEmitterDirect( dRec, its, medium, maxIntermediateInteractions, sampler->next2D()); if (!directRadiance.isZero()) { Float dp = dot(dRec.d, its.shFrame.n); if (dp > 0) EDir += directRadiance * dp; } } if (handleIndirect) { RadianceQueryRecord rRec(scene, sampler); rRec.newQuery(RadianceQueryRecord::ERadianceNoEmission, medium); rRec.its = its; if (!m_irrCache->get(rRec.its, EIndir)) handleMiss(RayDifferential(), rRec, EIndir); } return (EDir / (Float) nSamples) + EIndir; }
void process(const WorkUnit *workUnit, WorkResult *workResult, const bool &stop) { const RectangularWorkUnit *rect = static_cast<const RectangularWorkUnit *>(workUnit); IrradianceRecordVector *result = static_cast<IrradianceRecordVector *>(workResult); const SamplingIntegrator *integrator = m_subIntegrator.get(); Intersection its; RadianceQueryRecord rRec(m_scene, m_sampler); const int sx = rect->getOffset().x, sy = rect->getOffset().y, ex = sx + rect->getSize().x, ey = sy + rect->getSize().y; result->clear(); for (int y = sy; y < ey; y++) { for (int x = sx; x < ex; x++) { if (stop) break; Point2 pixelSample(x + .5f, y + .5f); RayDifferential ray; if (m_sensor->sampleRayDifferential(ray, pixelSample, Point2(0.5f), 0.5f).isZero()) continue; if (m_scene->rayIntersect(ray, its)) { const BSDF *bsdf = its.getBSDF(); if ((bsdf->getType() & BSDF::EAll) != BSDF::EDiffuseReflection) continue; Spectrum E; if (m_irrCache->get(its, E)) continue; /* Irradiance cache miss - create a record. The following generates stratified cosine-weighted samples and computes rotational + translational gradients */ m_hs->generateDirections(its); m_sampler->generate(Point2i(0)); for (unsigned int j=0; j<m_hs->getM(); j++) { for (unsigned int k=0; k<m_hs->getN(); k++) { HemisphereSampler::SampleEntry &entry = (*m_hs)(j, k); entry.dist = std::numeric_limits<Float>::infinity(); rRec.newQuery(RadianceQueryRecord::ERadianceNoEmission | RadianceQueryRecord::EDistance, m_sensor->getMedium()); rRec.extra = RadianceQueryRecord::ECacheQuery; rRec.depth = 2; entry.L = integrator->Li(RayDifferential(its.p, entry.d, 0.0f), rRec); entry.dist = rRec.dist; m_sampler->advance(); } } m_hs->process(its); result->put(m_irrCache->put(ray, its, *m_hs)); } } } }
void SamplingIntegrator::renderBlock(const Scene *scene, const Sensor *sensor, Sampler *sampler, ImageBlock *block, const bool &stop, const std::vector< TPoint2<uint8_t> > &points) const { Float diffScaleFactor = 1.0f / std::sqrt((Float) sampler->getSampleCount()); bool needsApertureSample = sensor->needsApertureSample(); bool needsTimeSample = sensor->needsTimeSample(); RadianceQueryRecord rRec(scene, sampler); Point2 apertureSample(0.5f); Float timeSample = 0.5f; RayDifferential sensorRay; block->clear(); uint32_t queryType = RadianceQueryRecord::ESensorRay; if (!sensor->getFilm()->hasAlpha()) /* Don't compute an alpha channel if we don't have to */ queryType &= ~RadianceQueryRecord::EOpacity; for (size_t i = 0; i<points.size(); ++i) { Point2i offset = Point2i(points[i]) + Vector2i(block->getOffset()); if (stop) break; sampler->generate(offset); for (size_t j = 0; j<sampler->getSampleCount(); j++) { rRec.newQuery(queryType, sensor->getMedium()); Point2 samplePos(Point2(offset) + Vector2(rRec.nextSample2D())); if (needsApertureSample) apertureSample = rRec.nextSample2D(); if (needsTimeSample) timeSample = rRec.nextSample1D(); Spectrum spec = sensor->sampleRayDifferential( sensorRay, samplePos, apertureSample, timeSample); sensorRay.scaleDifferential(diffScaleFactor); spec *= Li(sensorRay, rRec); block->put(samplePos, spec, rRec.alpha); sampler->advance(); } } }
void SampleIntegrator::renderBlock(const Scene *scene, const Camera *camera, Sampler *sampler, ImageBlock *block, const bool &stop, const std::vector<Point2i> *points) const { Point2 sample, lensSample; RayDifferential eyeRay; Float timeSample = 0; Spectrum spec; block->clear(); RadianceQueryRecord rRec(scene, sampler); bool needsLensSample = camera->needsLensSample(); bool needsTimeSample = camera->needsTimeSample(); const TabulatedFilter *filter = camera->getFilm()->getTabulatedFilter(); Float scaleFactor = 1.0f/std::sqrt((Float) sampler->getSampleCount()); if (points) { /* Use a prescribed traversal order (e.g. using a space-filling curve) */ if (!block->collectStatistics()) { for (size_t i=0; i<points->size(); ++i) { Point2i offset = (*points)[i] + Vector2i(block->getOffset()); if (stop) break; sampler->generate(); for (size_t j = 0; j<sampler->getSampleCount(); j++) { rRec.newQuery(RadianceQueryRecord::ECameraRay, camera->getMedium()); if (needsLensSample) lensSample = rRec.nextSample2D(); if (needsTimeSample) timeSample = rRec.nextSample1D(); sample = rRec.nextSample2D(); sample.x += offset.x; sample.y += offset.y; camera->generateRayDifferential(sample, lensSample, timeSample, eyeRay); eyeRay.scaleDifferential(scaleFactor); spec = Li(eyeRay, rRec); block->putSample(sample, spec, rRec.alpha, filter); sampler->advance(); } } } else { Spectrum mean, meanSqr; for (size_t i=0; i<points->size(); ++i) { Point2i offset = (*points)[i] + Vector2i(block->getOffset()); if (stop) break; sampler->generate(); mean = meanSqr = Spectrum(0.0f); for (size_t j = 0; j<sampler->getSampleCount(); j++) { rRec.newQuery(RadianceQueryRecord::ECameraRay, camera->getMedium()); if (needsLensSample) lensSample = rRec.nextSample2D(); if (needsTimeSample) timeSample = rRec.nextSample1D(); sample = rRec.nextSample2D(); sample.x += offset.x; sample.y += offset.y; camera->generateRayDifferential(sample, lensSample, timeSample, eyeRay); eyeRay.scaleDifferential(scaleFactor); spec = Li(eyeRay, rRec); /* Numerically robust online variance estimation using an algorithm proposed by Donald Knuth (TAOCP vol.2, 3rd ed., p.232) */ const Spectrum delta = spec - mean; mean += delta / ((Float) j+1); meanSqr += delta * (spec - mean); block->putSample(sample, spec, rRec.alpha, filter); block->setVariance(offset.x, offset.y, meanSqr / (Float) j, (int) j+1); sampler->advance(); } } } } else { /* Simple scanline traversal order */ const int sx = block->getOffset().x, sy = block->getOffset().y, ex = sx + block->getSize().x, ey = sy + block->getSize().y; if (!block->collectStatistics()) { for (int y = sy; y < ey; y++) { for (int x = sx; x < ex; x++) { if (stop) break; sampler->generate(); for (size_t j = 0; j<sampler->getSampleCount(); j++) { rRec.newQuery(RadianceQueryRecord::ECameraRay, camera->getMedium()); if (needsLensSample) lensSample = rRec.nextSample2D(); if (needsTimeSample) timeSample = rRec.nextSample1D(); sample = rRec.nextSample2D(); sample.x += x; sample.y += y; camera->generateRayDifferential(sample, lensSample, timeSample, eyeRay); eyeRay.scaleDifferential(scaleFactor); spec = Li(eyeRay, rRec); block->putSample(sample, spec, rRec.alpha, filter); sampler->advance(); } } } } else { Spectrum mean, meanSqr; for (int y = sy; y < ey; y++) { for (int x = sx; x < ex; x++) { if (stop) break; sampler->generate(); mean = meanSqr = Spectrum(0.0f); for (size_t j = 0; j<sampler->getSampleCount(); j++) { rRec.newQuery(RadianceQueryRecord::ECameraRay, camera->getMedium()); if (needsLensSample) lensSample = rRec.nextSample2D(); if (needsTimeSample) timeSample = rRec.nextSample1D(); sample = rRec.nextSample2D(); sample.x += x; sample.y += y; camera->generateRayDifferential(sample, lensSample, timeSample, eyeRay); eyeRay.scaleDifferential(scaleFactor); spec = Li(eyeRay, rRec); /* Numerically robust online variance estimation using an algorithm proposed by Donald Knuth (TAOCP vol.2, 3rd ed., p.232) */ const Spectrum delta = spec - mean; mean += delta / ((Float) j+1); meanSqr += delta * (spec - mean); block->putSample(sample, spec, rRec.alpha, filter); block->setVariance(x, y, meanSqr / (Float) j, (int) j+1); sampler->advance(); } } } } } }
void renderBlock(const Scene *scene, const Sensor *sensor, Sampler *sampler, ImageBlock *block, const bool &stop, const std::vector< TPoint2<uint8_t> > &points) const { Float diffScaleFactor = 1.0f / std::sqrt((Float)sampler->getSampleCount()); bool needsApertureSample = sensor->needsApertureSample(); bool needsTimeSample = sensor->needsTimeSample(); RadianceQueryRecord rRec(scene, sampler); Point2 apertureSample(0.5f); Float timeSample = 0.5f; RayDifferential sensorRay; block->clear(); uint32_t queryType = RadianceQueryRecord::ESensorRay; if (!sensor->getFilm()->hasAlpha()) /* Don't compute an alpha channel if we don't have to */ queryType &= ~RadianceQueryRecord::EOpacity; for (size_t i = 0; i < points.size(); ++i) { Point2i offset = Point2i(points[i]) + Vector2i(block->getOffset()); int index = offset.x + offset.y * width; if (stop) break; sampler->generate(offset); Float cntLdA = 0.f; std::vector<Float> cntLdW(m_numLobes, 0.f); for (size_t j = 0; j < sampler->getSampleCount(); j++) { rRec.newQuery(queryType, sensor->getMedium()); Point2 samplePos(Point2(offset) + Vector2(rRec.nextSample2D())); if (needsApertureSample) apertureSample = rRec.nextSample2D(); if (needsTimeSample) timeSample = rRec.nextSample1D(); Spectrum spec = sensor->sampleRayDifferential( sensorRay, samplePos, apertureSample, timeSample); sensorRay.scaleDifferential(diffScaleFactor); Spectrum oneTdA(0.f); Spectrum oneLdA(0.f); std::vector<Spectrum> oneTdW(m_numLobes, Spectrum(0.f)); std::vector<Spectrum> oneLdW(m_numLobes, Spectrum(0.f)); int albedoSegs = 0; spec *= Li(sensorRay, rRec, oneTdA, oneLdA, oneTdW, oneLdW, albedoSegs); block->put(samplePos, spec, rRec.alpha); bool goodSample = true; for (int c = 0; c < 3; c++) { if (!std::isfinite(oneLdA[c]) || oneLdA[c] < 0) { goodSample = false; break; } } if (goodSample) { LdA[index] += oneLdA; cntLdA += 1.f; } for (int k = 0; k < m_numLobes; k++) { goodSample = true; for (int c = 0; c < 3; c++) { if (!std::isfinite(oneLdW[k][c]) || oneLdW[k][c] < 0) { goodSample = false; break; } } if (goodSample) { LdW[k][index] += oneLdW[k]; cntLdW[k] += 1.f; } } imageSeg[index] |= albedoSegs; sampler->advance(); } if (cntLdA > 0.f) { LdA[index] /= cntLdA; } else { LdA[index] = Spectrum(0.f); } for (int k = 0; k < m_numLobes; k++) { if (cntLdW[k] > 0.f) { LdW[k][index] /= cntLdW[k]; } else { LdW[k][index] = Spectrum(0.f); } } } Float *data = new Float[(int)points.size() * 3]; std::string outfile = prefix + formatString("LdA_%03i_%03i.pfm", block->getOffset().x, block->getOffset().y); for (int i = 0; i < points.size(); i++) { Point2i p = Point2i(points[i]); int localIndex = p.x + p.y * block->getWidth(); Point2i offset = p + Vector2i(block->getOffset()); int globalIndex = offset.x + offset.y * width; Spectrum color(LdA[globalIndex]); for (int c = 0; c < 3; c++) { data[3 * localIndex + c] = color[c]; } } savePfm(outfile.c_str(), data, block->getWidth(), block->getHeight()); for (int k = 0; k < m_numLobes; k++) { outfile = prefix + formatString("LdW_l%02i_%03i_%03i.pfm", k, block->getOffset().x, block->getOffset().y); for (int i = 0; i < points.size(); i++) { Point2i p = Point2i(points[i]); int localIndex = p.x + p.y * block->getWidth(); Point2i offset = p + Vector2i(block->getOffset()); int globalIndex = offset.x + offset.y * width; Spectrum color(LdW[k][globalIndex]); for (int c = 0; c < 3; c++) { data[3 * localIndex + c] = color[c]; } } savePfm(outfile.c_str(), data, block->getWidth(), block->getHeight()); } outfile = prefix + formatString("image_seg_%03i_%03i.pfm", block->getOffset().x, block->getOffset().y); for (int i = 0; i < points.size(); i++) { Point2i p = Point2i(points[i]); int localIndex = p.x + p.y * block->getWidth(); Point2i offset = p + Vector2i(block->getOffset()); int globalIndex = offset.x + offset.y * width; Spectrum color(imageSeg[globalIndex]); for (int c = 0; c < 3; c++) { data[3 * localIndex + c] = color[c]; } } savePfm(outfile.c_str(), data, block->getWidth(), block->getHeight()); /* outfile = formatString("TdA_%03i_%03i.pfm", block->getOffset().x, block->getOffset().y); for (int i = 0; i < points.size(); i++) { Point2i p = Point2i(points[i]); int localIndex = p.x + p.y * block->getWidth(); Point2i offset = p + Vector2i(block->getOffset()); int globalIndex = offset.x + offset.y * width; Spectrum color(TdA[globalIndex] / Float(spp)); for (int c = 0; c < 3; c++) { data[3 * localIndex + c] = color[c]; } } savePfm(outfile.c_str(), data, block->getWidth(), block->getHeight()); */ delete[] data; }