Exemple #1
0
void PathVertex::evalPdfs(const PathVertex *prev, const PathEdge *prevEdge, const PathVertex &next,
        const PathEdge &nextEdge, float *forward, float *backward) const
{
    switch (_type) {
    case EmitterVertex:
        if (_sampler.emitter->isInfinite())
            // Positional pdf is constant for a fixed direction, which is the case
            // for connections to a point on an infinite emitter
            *forward = nextEdge.pdfForward*_record.emitter.point.pdf*next.cosineFactor(nextEdge.d);
        else
            *forward = nextEdge.pdfForward*next.cosineFactor(nextEdge.d)/nextEdge.rSq*
                    _sampler.emitter->directionalPdf(_record.emitter.point, DirectionSample(nextEdge.d));
        break;
    case CameraVertex:
        *forward = nextEdge.pdfForward*next.cosineFactor(nextEdge.d)/nextEdge.rSq*
                _sampler.camera->directionPdf(_record.camera.point, DirectionSample(nextEdge.d));
        break;
    case SurfaceVertex: {
        const SurfaceScatterEvent &event = _record.surface.event;
        Vec3f dPrev = event.frame.toLocal(-prevEdge->d);
        Vec3f dNext = event.frame.toLocal(nextEdge.d);
        *forward  = nextEdge .pdfForward *_sampler.bsdf->pdf(event.makeWarpedQuery(dPrev, dNext));
        *backward = prevEdge->pdfBackward*_sampler.bsdf->pdf(event.makeWarpedQuery(dNext, dPrev));
        if (!next .isInfiniteEmitter()) *forward  *= next .cosineFactor(nextEdge .d)/nextEdge .rSq;
        if (!prev->isInfiniteEmitter()) *backward *= prev->cosineFactor(prevEdge->d)/prevEdge->rSq;
        break;
    } case MediumVertex: {
        *forward  = nextEdge .pdfForward *_sampler.phase->pdf(prevEdge->d,   nextEdge.d);
        *backward = prevEdge->pdfBackward*_sampler.phase->pdf(-nextEdge.d, -prevEdge->d);
        if (!next .isInfiniteEmitter()) *forward  *= next .cosineFactor(nextEdge .d)/nextEdge .rSq;
        if (!prev->isInfiniteEmitter()) *backward *= prev->cosineFactor(prevEdge->d)/prevEdge->rSq;
        break;
    }}
}
Exemple #2
0
bool PinholeCamera::sampleDirect(const Vec3f &p, PathSampleGenerator &sampler, LensSample &sample) const
{
    sample.d = _pos - p;

    if (!evalDirection(sampler, PositionSample(), DirectionSample(-sample.d), sample.weight, sample.pixel))
        return false;

    float rSq = sample.d.lengthSq();
    sample.dist = std::sqrt(rSq);
    sample.d /= sample.dist;
    sample.weight /= rSq;
    return true;
}
Exemple #3
0
Vec3f PathVertex::eval(const Vec3f &d, bool adjoint) const
{
    switch (_type) {
    case EmitterVertex:
        if (_sampler.emitter->isInfinite())
            return _sampler.emitter->evalPositionalEmission(_record.emitter.point);
        else
            return _sampler.emitter->evalDirectionalEmission(_record.emitter.point, DirectionSample(d));
    case CameraVertex:
        return Vec3f(0.0f);
    case SurfaceVertex:
        return _sampler.bsdf->eval(_record.surface.event.makeWarpedQuery(
                _record.surface.event.wi,
                _record.surface.event.frame.toLocal(d)),
                adjoint);
    case MediumVertex:
        return _sampler.phase->eval(_record.medium.wi, d);
    default:
        return Vec3f(0.0f);
    }
}
void LightTracer::traceSample(PathSampleGenerator &sampler)
{
    float lightPdf;
    const Primitive *light = chooseLightAdjoint(sampler, lightPdf);
    const Medium *medium = light->extMedium().get();

    PositionSample point;
    if (!light->samplePosition(sampler, point))
        return;
    DirectionSample direction;
    if (!light->sampleDirection(sampler, point, direction))
        return;
    sampler.advancePath();

    Vec3f throughput(point.weight/lightPdf);

    LensSample splat;
    if (_settings.minBounces == 0 && !light->isInfinite() && _scene->cam().sampleDirect(point.p, sampler, splat)) {
        Ray shadowRay(point.p, splat.d);
        shadowRay.setFarT(splat.dist);

        Vec3f transmission = generalizedShadowRay(shadowRay, medium, nullptr, 0);
        if (transmission != 0.0f) {
            Vec3f value = throughput*transmission*splat.weight
                    *light->evalDirectionalEmission(point, DirectionSample(splat.d));
            _splatBuffer->splatFiltered(splat.pixel, value);
        }
    }
    sampler.advancePath();

    Ray ray(point.p, direction.d);
    throughput *= direction.weight;

    VolumeScatterEvent volumeEvent;
    SurfaceScatterEvent surfaceEvent;
    IntersectionTemporary data;
    IntersectionInfo info;
    Medium::MediumState state;
    state.reset();
    Vec3f emission(0.0f);

    int bounce = 0;
    bool wasSpecular = true;
    bool didHit = _scene->intersect(ray, data, info);
    while ((didHit || medium) && bounce < _settings.maxBounces - 1) {
        bool hitSurface = true;
        if (medium) {
            volumeEvent = VolumeScatterEvent(&sampler, throughput, ray.pos(), ray.dir(), ray.farT());
            if (!medium->sampleDistance(volumeEvent, state))
                break;
            throughput *= volumeEvent.weight;
            volumeEvent.weight = Vec3f(1.0f);
            hitSurface = volumeEvent.t == volumeEvent.maxT;
            if (hitSurface && !didHit)
                break;
        }

        if (hitSurface) {
            surfaceEvent = makeLocalScatterEvent(data, info, ray, &sampler);

            Vec3f weight;
            Vec2f pixel;
            if (surfaceLensSample(_scene->cam(), surfaceEvent, medium, bounce + 1, ray, weight, pixel))
                _splatBuffer->splatFiltered(pixel, weight*throughput);

            if (!handleSurface(surfaceEvent, data, info, medium, bounce,
                    true, false, ray, throughput, emission, wasSpecular, state))
                break;
        } else {
            volumeEvent.p += volumeEvent.t*volumeEvent.wi;

            Vec3f weight;
            Vec2f pixel;
            if (volumeLensSample(_scene->cam(), volumeEvent, medium, bounce + 1, ray, weight, pixel))
                _splatBuffer->splatFiltered(pixel, weight*throughput);

            if (!handleVolume(volumeEvent, medium, bounce,
                    true, false, ray, throughput, emission, wasSpecular, state))
                break;
        }

        if (throughput.max() == 0.0f)
            break;
        if (std::isnan(ray.dir().sum() + ray.pos().sum()))
            break;
        if (std::isnan(throughput.sum()))
            break;

        sampler.advancePath();
        bounce++;
        if (bounce < _settings.maxBounces)
            didHit = _scene->intersect(ray, data, info);
    }
}