Spectrum MetropolisRenderer::PathL(const MLTSample &sample, const Scene *scene, MemoryArena &arena, const Camera *camera, const Distribution1D *lightDistribution, PathVertex *cameraPath, PathVertex *lightPath, RNG &rng) const { // Generate camera path from camera path samples PBRT_STARTED_GENERATING_CAMERA_RAY((CameraSample *)(&sample.cameraSample)); RayDifferential cameraRay; float cameraWt = camera->GenerateRayDifferential(sample.cameraSample, &cameraRay); cameraRay.ScaleDifferentials(1.f / sqrtf(nPixelSamples)); PBRT_FINISHED_GENERATING_CAMERA_RAY((CameraSample *)(&sample.cameraSample), &cameraRay, cameraWt); RayDifferential escapedRay; Spectrum escapedAlpha; uint32_t cameraLength = GeneratePath(cameraRay, cameraWt, scene, arena, sample.cameraPathSamples, cameraPath, &escapedRay, &escapedAlpha); if (!bidirectional) { // Compute radiance along path using path tracing return Lpath(scene, cameraPath, cameraLength, arena, sample.lightingSamples, rng, sample.cameraSample.time, lightDistribution, escapedRay, escapedAlpha); } else { // Sample light ray and apply bidirectional path tracing // Choose light and sample ray to start light path PBRT_MLT_STARTED_SAMPLE_LIGHT_FOR_BIDIR(); float lightPdf, lightRayPdf; uint32_t lightNum = lightDistribution->SampleDiscrete(sample.lightNumSample, &lightPdf); const Light *light = scene->lights[lightNum]; Ray lightRay; Normal Nl; LightSample lrs(sample.lightRaySamples[0], sample.lightRaySamples[1], sample.lightRaySamples[2]); Spectrum lightWt = light->Sample_L(scene, lrs, sample.lightRaySamples[3], sample.lightRaySamples[4], sample.cameraSample.time, &lightRay, &Nl, &lightRayPdf); PBRT_MLT_FINISHED_SAMPLE_LIGHT_FOR_BIDIR(); if (lightWt.IsBlack() || lightRayPdf == 0.f) { // Compute radiance along path using path tracing return Lpath(scene, cameraPath, cameraLength, arena, sample.lightingSamples, rng, sample.cameraSample.time, lightDistribution, escapedRay, escapedAlpha); } else { // Compute radiance along paths using bidirectional path tracing lightWt *= AbsDot(Normalize(Nl), lightRay.d) / (lightPdf * lightRayPdf); uint32_t lightLength = GeneratePath(RayDifferential(lightRay), lightWt, scene, arena, sample.lightPathSamples, lightPath, NULL, NULL); return Lbidir(scene, cameraPath, cameraLength, lightPath, lightLength, arena, sample.lightingSamples, rng, sample.cameraSample.time, lightDistribution, escapedRay, escapedAlpha); } } }
// RPFSamplerRendererTask Definitions void RPFSamplerRendererTask::Run() { PBRT_STARTED_RENDERTASK(taskNum); // Get sub-_Sampler_ for _RPFSamplerRendererTask_ Sampler *sampler = mainSampler->GetSubSampler(taskNum, taskCount); if (!sampler) { reporter.Update(); PBRT_FINISHED_RENDERTASK(taskNum); return; } // Declare local variables used for rendering loop MemoryArena arena; RNG rng(taskNum); // Allocate space for samples and intersections int maxSamples = sampler->MaximumSampleCount(); Sample *samples = origSample->Duplicate(maxSamples); RayDifferential *rays = new RayDifferential[maxSamples]; Spectrum *Ls = new Spectrum[maxSamples]; Spectrum *Ts = new Spectrum[maxSamples]; Intersection *isects = new Intersection[maxSamples]; // Get samples from _Sampler_ and update image int sampleCount; while ((sampleCount = sampler->GetMoreSamples(samples, rng)) > 0) { // Generate camera rays and compute radiance along rays for (int i = 0; i < sampleCount; ++i) { // Find camera ray for _sample[i]_ PBRT_STARTED_GENERATING_CAMERA_RAY(&samples[i]); float rayWeight = camera->GenerateRayDifferential(samples[i], &rays[i]); rays[i].ScaleDifferentials(1.f / sqrtf(sampler->samplesPerPixel)); PBRT_FINISHED_GENERATING_CAMERA_RAY(&samples[i], &rays[i], rayWeight); // Evaluate radiance along camera ray PBRT_STARTED_CAMERA_RAY_INTEGRATION(&rays[i], &samples[i]); if (visualizeObjectIds) { if (rayWeight > 0.f && scene->Intersect(rays[i], &isects[i])) { // random shading based on shape id... /* This renderer can optionally ignore the surface and volume integrators and randomly shade objects based on their shape and primitive id values. This can be useful to visualize the tessellation of complex objects and search for problems in geometric models.*/ uint32_t ids[2] = { isects[i].shapeId, isects[i].primitiveId }; uint32_t h = hash((char *)ids, sizeof(ids)); float rgb[3] = { (h & 0xff), (h >> 8) & 0xff, (h >> 16) & 0xff }; Ls[i] = Spectrum::FromRGB(rgb); Ls[i] /= 255.f; } else Ls[i] = 0.f; } else { //Normal shading based on rendering equation if (rayWeight > 0.f)
// SamplerRendererTask Definitions void SamplerRendererTask::Run() { PBRT_STARTED_RENDERTASK(taskNum); // Get sub-_Sampler_ for _SamplerRendererTask_ Sampler *sampler = mainSampler->GetSubSampler(taskNum, taskCount); if (!sampler) { reporter.Update(); PBRT_FINISHED_RENDERTASK(taskNum); return; } // Declare local variables used for rendering loop MemoryArena arena; /*Full Random initialize SEED with Time (ToDo Metropolis)*/ /*old * RNG rng(taskNum); */ int rseed; if (PbrtOptions.fullRandom) rseed = taskNum * time(NULL); else rseed = taskNum; RNG rng(rseed); // Allocate space for samples and intersections int maxSamples = sampler->MaximumSampleCount(); Sample *samples = origSample->Duplicate(maxSamples); RayDifferential *rays = new RayDifferential[maxSamples]; Spectrum *Ls = new Spectrum[maxSamples]; Spectrum *Ts = new Spectrum[maxSamples]; Intersection *isects = new Intersection[maxSamples]; // Get samples from _Sampler_ and update image int sampleCount; while ((sampleCount = sampler->GetMoreSamples(samples, rng)) > 0) { // Generate camera rays and compute radiance along rays for (int i = 0; i < sampleCount; ++i) { // Find camera ray for _sample[i]_ PBRT_STARTED_GENERATING_CAMERA_RAY(&samples[i]); float rayWeight = camera->GenerateRayDifferential(samples[i], &rays[i]); rays[i].ScaleDifferentials(1.f / sqrtf(sampler->samplesPerPixel)); PBRT_FINISHED_GENERATING_CAMERA_RAY(&samples[i], &rays[i], rayWeight); // Evaluate radiance along camera ray PBRT_STARTED_CAMERA_RAY_INTEGRATION(&rays[i], &samples[i]); if (visualizeObjectIds) { if (rayWeight > 0.f && scene->Intersect(rays[i], &isects[i])) { // random shading based on shape id... uint32_t ids[2] = { isects[i].shapeId, isects[i].primitiveId }; uint32_t h = hash((char *)ids, sizeof(ids)); float rgb[3] = { (h & 0xff), (h >> 8) & 0xff, (h >> 16) & 0xff }; Ls[i] = Spectrum::FromRGB(rgb); Ls[i] /= 255.f; } else Ls[i] = 0.f; } else { if (rayWeight > 0.f)
// SamplerRendererTask Definitions void SamplerRendererTask::Run() { PBRT_STARTED_RENDERTASK(taskNum); // Get sub-_Sampler_ for _SamplerRendererTask_ Sampler *sampler = mainSampler->GetSubSampler(taskNum, taskCount); if (!sampler) { reporter.Update(); PBRT_FINISHED_RENDERTASK(taskNum); return; } // Declare local variables used for rendering loop MemoryArena arena; RNG rng(taskNum); // Allocate space for samples and intersections int maxSamples = sampler->MaximumSampleCount(); Sample *samples = origSample->Duplicate(maxSamples); RayDifferential *rays = new RayDifferential[maxSamples]; Spectrum *Ls = new Spectrum[maxSamples]; Spectrum *Ts = new Spectrum[maxSamples]; Intersection *isects = new Intersection[maxSamples]; // Get samples from \use{Sampler} and update image int sampleCount; while ((sampleCount = sampler->GetMoreSamples(samples, rng)) > 0) { // Generate camera rays and compute radiance along rays for (int i = 0; i < sampleCount; ++i) { // Find camera ray for _sample[i]_ PBRT_STARTED_GENERATING_CAMERA_RAY(&samples[i]); float rayWeight = camera->GenerateRayDifferential(samples[i], &rays[i]); PBRT_FINISHED_GENERATING_CAMERA_RAY(&samples[i], &rays[i], rayWeight); // Evaluate radiance along camera ray PBRT_STARTED_CAMERA_RAY_INTEGRATION(&rays[i], &samples[i]); if (rayWeight > 0.f) Ls[i] = rayWeight * renderer->Li(scene, rays[i], &samples[i], rng, arena, &isects[i], &Ts[i]); else { Ls[i] = 0.f; Ts[i] = 1.f; } // Issue warning if unexpected radiance value returned if (Ls[i].HasNaNs()) { Error("Not-a-number radiance value returned " "for image sample. Setting to black."); Ls[i] = Spectrum(0.f); } else if (Ls[i].y() < -1e-5) { Error("Negative luminance value, %f, returned" "for image sample. Setting to black.", Ls[i].y()); Ls[i] = Spectrum(0.f); } else if (isinf(Ls[i].y())) { Error("Infinite luminance value returned" "for image sample. Setting to black."); Ls[i] = Spectrum(0.f); } PBRT_FINISHED_CAMERA_RAY_INTEGRATION(&rays[i], &samples[i], &Ls[i]); } // Report sample results to _Sampler_, add contributions to image if (sampler->ReportResults(samples, rays, Ls, isects, sampleCount)) { for (int i = 0; i < sampleCount; ++i) { PBRT_STARTED_ADDING_IMAGE_SAMPLE(&samples[i], &rays[i], &Ls[i], &Ts[i]); camera->film->AddSample(samples[i], Ls[i]); PBRT_FINISHED_ADDING_IMAGE_SAMPLE(); } } // Free \use{MemoryArena} memory from computing image sample values arena.FreeAll(); } // Clean up after \use{SamplerRendererTask} is done with its image region camera->film->UpdateDisplay(sampler->xPixelStart, sampler->yPixelStart, sampler->xPixelEnd+1, sampler->yPixelEnd+1); delete sampler; delete[] samples; delete[] rays; delete[] Ls; delete[] Ts; delete[] isects; reporter.Update(); PBRT_FINISHED_RENDERTASK(taskNum); }