bool ExponentialMedium::sampleDistance(PathSampleGenerator &sampler, const Ray &ray, MediumState &state, MediumSample &sample) const { if (state.bounce > _maxBounce) return false; float x = _falloffScale*(ray.pos() - _unitPoint).dot(_unitFalloffDirection); float dx = _falloffScale*ray.dir().dot(_unitFalloffDirection); float maxT = ray.farT(); if (_absorptionOnly) { if (maxT == Ray::infinity() && dx <= 0.0f) return false; sample.t = maxT; sample.weight = std::exp(-_sigmaT*densityIntegral(x, dx, ray.farT())); sample.pdf = 1.0f; sample.exited = true; } else { int component = sampler.nextDiscrete(3); float sigmaTc = _sigmaT[component]; float xi = 1.0f - sampler.next1D(); float logXi = std::log(xi); float t = inverseOpticalDepth(x, dx, sigmaTc, logXi); sample.t = min(t, maxT); sample.weight = std::exp(-_sigmaT*densityIntegral(x, dx, sample.t)); sample.exited = (t >= maxT); if (sample.exited) { sample.pdf = sample.weight.avg(); } else { float rho = density(x, dx, sample.t); sample.pdf = (rho*_sigmaT*sample.weight).avg(); sample.weight *= rho*_sigmaS; } sample.weight /= sample.pdf; state.advance(); } sample.p = ray.pos() + sample.t*ray.dir(); sample.phase = _phaseFunction.get(); return true; }
bool AtmosphericMedium::sampleDistance(PathSampleGenerator &sampler, const Ray &ray, MediumState &state, MediumSample &sample) const { if (state.bounce > _maxBounce) return false; Vec3f p = (ray.pos() - _center); float t0 = p.dot(ray.dir()); float h = (p - t0*ray.dir()).length(); float maxT = ray.farT() + t0; if (_absorptionOnly) { sample.t = ray.farT(); sample.weight = std::exp(-_sigmaT*densityIntegral(h, t0, maxT)); sample.pdf = 1.0f; sample.exited = true; } else { int component = sampler.nextDiscrete(3); float sigmaTc = _sigmaT[component]; float xi = 1.0f - sampler.next1D(); float t = inverseOpticalDepth(h, t0, sigmaTc, xi); sample.t = min(t, maxT); sample.weight = std::exp(-_sigmaT*densityIntegral(h, t0, sample.t)); sample.exited = (t >= maxT); if (sample.exited) { sample.pdf = sample.weight.avg(); } else { float rho = density(h, sample.t); sample.pdf = (rho*_sigmaT*sample.weight).avg(); sample.weight *= rho*_sigmaS; } sample.weight /= sample.pdf; sample.t -= t0; state.advance(); } sample.p = ray.pos() + sample.t*ray.dir(); sample.phase = _phaseFunction.get(); return true; }
bool HomogeneousMedium::sampleDistance(PathSampleGenerator &sampler, const Ray &ray, MediumState &state, MediumSample &sample) const { if (state.bounce > _maxBounce) return false; float maxT = ray.farT(); if (_absorptionOnly) { if (maxT == Ray::infinity()) return false; sample.t = maxT; sample.weight = std::exp(-_sigmaT*maxT); sample.pdf = 1.0f; sample.exited = true; } else { int component = sampler.nextDiscrete(3); float sigmaTc = _sigmaT[component]; float t = -std::log(1.0f - sampler.next1D())/sigmaTc; sample.t = min(t, maxT); sample.weight = std::exp(-sample.t*_sigmaT); sample.exited = (t >= maxT); if (sample.exited) { sample.pdf = sample.weight.avg(); } else { sample.pdf = (_sigmaT*sample.weight).avg(); sample.weight *= _sigmaS; } sample.weight /= sample.pdf; state.advance(); } sample.p = ray.pos() + sample.t*ray.dir(); sample.phase = _phaseFunction.get(); return true; }