void Light::SHProject(const PbrtPoint &p, float pEpsilon, int lmax, const Scene *scene, bool computeLightVisibility, float time, RNG &rng, Spectrum *coeffs) const { for (int i = 0; i < SHTerms(lmax); ++i) coeffs[i] = 0.f; uint32_t ns = RoundUpPow2(nSamples); uint32_t scramble1D = rng.RandomUInt(); uint32_t scramble2D[2] = { rng.RandomUInt(), rng.RandomUInt() }; float *Ylm = ALLOCA(float, SHTerms(lmax)); for (uint32_t i = 0; i < ns; ++i) { // Compute incident radiance sample from _light_, update SH _coeffs_ float u[2], pdf; Sample02(i, scramble2D, u); LightSample lightSample(u[0], u[1], VanDerCorput(i, scramble1D)); Vector wi; VisibilityTester vis; Spectrum Li = Sample_L(p, pEpsilon, lightSample, time, &wi, &pdf, &vis); if (!Li.IsBlack() && pdf > 0.f && (!computeLightVisibility || vis.Unoccluded(scene))) { // Add light sample contribution to MC estimate of SH coefficients SHEvaluate(wi, lmax, Ylm); for (int j = 0; j < SHTerms(lmax); ++j) coeffs[j] += Li * Ylm[j] / (pdf * ns); } } }
void ZeroTwoSequenceSampler::StartPixel(const Point2i &p) { // Generate 1D and 2D pixel sample components using $(0,2)$-sequence for (size_t i = 0; i < samples1D.size(); ++i) VanDerCorput(1, samplesPerPixel, &samples1D[i][0], rng); for (size_t i = 0; i < samples2D.size(); ++i) Sobol2D(1, samplesPerPixel, &samples2D[i][0], rng); // Generate 1D and 2D array samples using $(0,2)$-sequence for (size_t i = 0; i < samples1DArraySizes.size(); ++i) VanDerCorput(samples1DArraySizes[i], samplesPerPixel, &sampleArray1D[i][0], rng); for (size_t i = 0; i < samples2DArraySizes.size(); ++i) Sobol2D(samples2DArraySizes[i], samplesPerPixel, &sampleArray2D[i][0], rng); PixelSampler::StartPixel(p); }
// MaxMinDistSampler Method Definitions void MaxMinDistSampler::StartPixel(const Point2i &p) { Float invSPP = (Float)1 / samplesPerPixel; for (int i = 0; i < samplesPerPixel; ++i) samples2D[0][i] = Point2f(i * invSPP, SampleGeneratorMatrix(CPixel, i)); Shuffle(&samples2D[0][0], samplesPerPixel, 1, rng); // Generate remaining samples for _MaxMinDistSampler_ for (size_t i = 0; i < samples1D.size(); ++i) VanDerCorput(1, samplesPerPixel, &samples1D[i][0], rng); for (size_t i = 1; i < samples2D.size(); ++i) Sobol2D(1, samplesPerPixel, &samples2D[i][0], rng); for (size_t i = 0; i < samples1DArraySizes.size(); ++i) { int count = samples1DArraySizes[i]; VanDerCorput(count, samplesPerPixel, &sampleArray1D[i][0], rng); } for (size_t i = 0; i < samples2DArraySizes.size(); ++i) { int count = samples2DArraySizes[i]; Sobol2D(count, samplesPerPixel, &sampleArray2D[i][0], rng); } PixelSampler::StartPixel(p); }
void DipoleSubsurfaceIntegrator::Preprocess(const Scene *scene, const Camera *camera, const Renderer *renderer) { if (scene->lights.size() == 0) return; vector<SurfacePoint> pts; // Get _SurfacePoint_s for translucent objects in scene if (filename != "") { // Initialize _SurfacePoint_s from file vector<float> fpts; if (ReadFloatFile(filename.c_str(), &fpts)) { if ((fpts.size() % 8) != 0) Error("Excess values (%d) in points file \"%s\"", int(fpts.size() % 8), filename.c_str()); for (u_int i = 0; i < fpts.size(); i += 8) pts.push_back(SurfacePoint(Point(fpts[i], fpts[i+1], fpts[i+2]), Normal(fpts[i+3], fpts[i+4], fpts[i+5]), fpts[i+6], fpts[i+7])); } } if (pts.size() == 0) { Point pCamera = camera->CameraToWorld(camera->shutterOpen, Point(0, 0, 0)); FindPoissonPointDistribution(pCamera, camera->shutterOpen, minSampleDist, scene, &pts); } // Compute irradiance values at sample points RNG rng; MemoryArena arena; PBRT_SUBSURFACE_STARTED_COMPUTING_IRRADIANCE_VALUES(); ProgressReporter progress(pts.size(), "Computing Irradiances"); for (uint32_t i = 0; i < pts.size(); ++i) { SurfacePoint &sp = pts[i]; Spectrum E(0.f); for (uint32_t j = 0; j < scene->lights.size(); ++j) { // Add irradiance from light at point const Light *light = scene->lights[j]; Spectrum Elight = 0.f; int nSamples = RoundUpPow2(light->nSamples); uint32_t scramble[2] = { rng.RandomUInt(), rng.RandomUInt() }; uint32_t compScramble = rng.RandomUInt(); for (int s = 0; s < nSamples; ++s) { float lpos[2]; Sample02(s, scramble, lpos); float lcomp = VanDerCorput(s, compScramble); LightSample ls(lpos[0], lpos[1], lcomp); Vector wi; float lightPdf; VisibilityTester visibility; Spectrum Li = light->Sample_L(sp.p, sp.rayEpsilon, ls, camera->shutterOpen, &wi, &lightPdf, &visibility); if (Dot(wi, sp.n) <= 0.) continue; if (Li.IsBlack() || lightPdf == 0.f) continue; Li *= visibility.Transmittance(scene, renderer, NULL, rng, arena); if (visibility.Unoccluded(scene)) Elight += Li * AbsDot(wi, sp.n) / lightPdf; } E += Elight / nSamples; } if (E.y() > 0.f) { irradiancePoints.push_back(IrradiancePoint(sp, E)); PBRT_SUBSURFACE_COMPUTED_IRRADIANCE_AT_POINT(&sp, &E); } arena.FreeAll(); progress.Update(); } progress.Done(); PBRT_SUBSURFACE_FINISHED_COMPUTING_IRRADIANCE_VALUES(); // Create octree of clustered irradiance samples octree = octreeArena.Alloc<SubsurfaceOctreeNode>(); for (uint32_t i = 0; i < irradiancePoints.size(); ++i) octreeBounds = Union(octreeBounds, irradiancePoints[i].p); for (uint32_t i = 0; i < irradiancePoints.size(); ++i) octree->Insert(octreeBounds, &irradiancePoints[i], octreeArena); octree->InitHierarchy(); }
void SamplerUtil::Samples02(DOUBLE* samples, UINT32 n) { for (UINT32 i = 0; i < n; ++i) { *(samples++) = VanDerCorput(i + 1, 3); *(samples++) = Sobol(i + 1, 2); } }