void VolumePatIntegrator::EyeRandomWalk(const Scene *scene, const Ray &eyeRay, VolumeVertexList& vertexList, RNG &rng) const { // Do a random walk for the eye ray in the volume Spectrum cummulative(1.f); // Find the intersection between the eye ray and the volume VolumeRegion *vr = scene->volumeRegion; float t0, t1; if (!vr || !vr->IntersectP(eyeRay, &t0, &t1) || (t1-t0) == 0.f || t0 < 0.f) { return; } // Find the intersection point between the sampled light ray and the volume RayDifferential ray(eyeRay); Point p = ray(t0), pPrev; uint64_t bounces = 0; while(vr->WorldBound().Inside(p)) { Vector wi = -ray.d; const Spectrum sigma_a = vr->Sigma_a(p, wi, eyeRay.time); const Spectrum sigma_s = vr->Sigma_s(p, wi, eyeRay.time); const Spectrum STER = vr->STER(p, wi, eyeRay.time); // Construct and add the _eyeVertex_ to the _vertexList_ VolumeVertex eyeVertex(p, wi, sigma_a, sigma_s, cummulative, 1.0); vertexList.push_back(eyeVertex); // Sample the direction of the next event float directionPdf = 1.f; Vector wo; if(STER.y() > rng.RandomFloat()) { // Change the ray direction due to a scattering event at _p_ if(!vr->SampleDirection(p, wi, wo, &directionPdf, rng)) { break; // Direction error } // Account for the losses due to the scattering event at _p_ cummulative *= sigma_s * vr->p(p, wi, wo, ray.time); } else { // Account only for the trnsmittance between the previous and the // next events becuse there is no direction change. wo = ray.d; } // Sample the distance of the next event ray = RayDifferential(p, wo, 0, INFINITY); float tDist; float distancePdf = 1.f; Point Psample; if(!vr->SampleDistance(ray, &tDist, Psample, &distancePdf, rng)) { break; // The sampled point is outside the volume } // Account for the sampling Pdfs from sampling a direction and/or distance const float pdf = distancePdf * directionPdf; cummulative *= 1 / pdf; // Update the events and account for the transmittance between the events pPrev = p; p = Psample; const Ray tauRay(pPrev, p - pPrev, 0.f, 1.f, ray.time, ray.depth); const Spectrum stepTau = vr->tau(tauRay, .5f * stepSize, rng.RandomFloat()); const Spectrum TrPP = Exp(-stepTau); cummulative *= TrPP; // Possibly terminate ray marching if _cummulative_ is small if (cummulative.y() < 1e-3) { const float continueProb = .5f; if (rng.RandomFloat() > continueProb) { cummulative = 0.f; break; } cummulative /= continueProb; } // Terminate if bounces are more than requested bounces++; if (bounces > maxDepth) { break; } } }
Spectrum VSDScatteringIntegrator::LiMultiple(const Scene *scene, const Renderer *renderer, const RayDifferential &ray, const Sample *sample, RNG &rng, Spectrum *T, MemoryArena &arena) const { VolumeRegion *vr = scene->volumeRegion; float t0, t1; vr->IntersectP(ray, &t0, &t1); // Do multiple scattering volume integration in _vr_ Spectrum Lv(0.); // Prepare for random walk Spectrum Tr(1.f); Point p = ray(t0), pPrev = ray.o; // printf("%f %f %f, ", p.x, p.y, p.z); int steps = 0; // Sample the events in a random walk // BBox bb = vr->WorldBound(); // printf("%f %f %f & %f %f %f \n", // bb.pMin.x, bb.pMin.y, bb.pMin.z, bb.pMax.x, bb.pMax.y, bb.pMax.z); while(vr->WorldBound().Inside(p)) { //printf("%f %f %f %d \n", p.x, p.y, p.z, steps); steps++; // Sample direction Vector wi = -ray.d, wo; float pdfDirection = 0.f; if(!vr->SampleDirection(p, wi, wo, &pdfDirection, rng)) { // printf("return 1 \n"); return Lv; } Ray r(p, wo, 0); // Sample a distance float pdfDistance = 0.f; float tDist; Point pSample; if(!vr->SampleDistance(r, &tDist, pSample, &pdfDistance, rng)) { // printf("return 2 \n"); return Lv; } // Compute the transmittance pPrev = p; p = r(tDist); Ray tauRay(pPrev, p - pPrev, 0.f, 1.f, r.time, r.depth); Spectrum stepTau = vr->tau(tauRay, .5f * stepSize, rng.RandomFloat()); Tr *= Exp(-stepTau); // Possibly terminate random walk if transmittance is small if (Tr.y() < 1e-3) { const float continueProb = .5f; if (rng.RandomFloat() > continueProb) { Tr = 0.f; // printf("return 3 \n"); break; } Tr /= continueProb; } // Compute emission term at _p_ Lv += Tr * vr->PhotonDensity(p) / (pdfDistance * pdfDirection); } // printf("%f %f %f %d \n", p.x, p.y, p.z, steps); // printf("%d, ", steps); return Lv; }