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; } } }