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 AtmosphericMedium::sampleDistance(VolumeScatterEvent &event, MediumState &state) const { if (state.bounce > _maxBounce) return false; Vec2f tSpan; if (!sphereMinTMaxT(event.p, event.wi, tSpan, _rT) || event.maxT < tSpan.x()) { event.t = event.maxT; event.throughput = Vec3f(1.0f); return true; } if (state.firstScatter) { sampleColorChannel(event, state); } else { event.throughput = Vec3f(0.0f); event.throughput[state.component] = 1.0f; } state.advance(); float targetDepth = -std::log(1.0f - event.sampler->next1D())/_sigmaS[state.component]; float minT = max(0.0f, tSpan.x()); Vec3f p = event.p + minT*event.wi; float maxT = min(event.maxT - minT, tSpan.y()); float sampledT; if (_cloudThickness) { targetDepth *= _sigmaS[state.component]; Vec4f depthAndT = spectralOpticalDepthAndT(p, event.wi, maxT, targetDepth, state.component, event.sampler->next1D()); sampledT = depthAndT.w(); } else { Vec2f depthAndT = opticalDepthAndT(p, event.wi, maxT, targetDepth); sampledT = depthAndT.y(); } event.t = sampledT == maxT ? event.maxT : (sampledT + minT); 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; }