예제 #1
0
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;
}
예제 #2
0
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;
}
예제 #3
0
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;
}