Ejemplo n.º 1
0
Spectrum VolumePatIntegrator::EstimateDirectLight(const Scene *scene,
        const Renderer *renderer, MemoryArena &arena, const Light *light,
        const Point &p, const Normal &n, const Vector &wo, float rayEpsilon,
        float time, RNG &rng, const LightSample &lightSample) const {
    VolumeRegion *vr = scene->volumeRegion;
    if (!vr) Spectrum(0.);
    Spectrum Ld(0.);
    // Sample light source.
    Vector wi;
    float lightPdf;
    VisibilityTester visibility;
    Spectrum Li = light->Sample_L(p, rayEpsilon, lightSample, time,
                                  &wi, &lightPdf, &visibility);
    if (lightPdf > 0. && !Li.IsBlack() && visibility.Unoccluded(scene)) {
        // Add light's contribution to reflected radiance
        Li *= visibility.Transmittance(scene, renderer, NULL, rng, arena);
        // Li *= PowerHeuristic(1, lightPdf, 1, (1/M_PI_4));
        Ld += vr->p(p, -wi, wo, time) * vr->Sigma_s(p, wo, time) * Li / lightPdf;
    }
    return Ld;
}
Ejemplo n.º 2
0
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;
        }
    }
}
Ejemplo n.º 3
0
Spectrum VolumePatIntegrator::Li_Single(const Scene *scene, const Renderer *renderer,
        const RayDifferential &ray, const Sample *sample, RNG &rng,
        Spectrum *T, MemoryArena &arena) const {
    VolumeRegion *vr = scene->volumeRegion;
    float t0, t1;
    if (!vr || !vr->IntersectP(ray, &t0, &t1) || (t1-t0) == 0.f) {
        *T = 1.f;
        return 0.f;
    }
    // Do single scattering volume integration in _vr_
    Spectrum Lv(0.);

    // Prepare for volume integration stepping
    int nSamples = Ceil2Int((t1-t0) / stepSize);
    float step = (t1 - t0) / nSamples;
    Spectrum Tr(1.f);
    Point p = ray(t0), pPrev;
    Vector w = -ray.d;
    t0 += sample->oneD[scatterSampleOffset][0] * step;

    // Compute sample patterns for single scattering samples
    float *lightNum = arena.Alloc<float>(nSamples);
    LDShuffleScrambled1D(1, nSamples, lightNum, rng);
    float *lightComp = arena.Alloc<float>(nSamples);
    LDShuffleScrambled1D(1, nSamples, lightComp, rng);
    float *lightPos = arena.Alloc<float>(2*nSamples);
    LDShuffleScrambled2D(1, nSamples, lightPos, rng);
    uint32_t sampOffset = 0;
    for (int i = 0; i < nSamples; ++i, t0 += step) {
        // Advance to sample at _t0_ and update _T_
        pPrev = p;
        p = ray(t0);
        Ray tauRay(pPrev, p - pPrev, 0.f, 1.f, ray.time, ray.depth);
        Spectrum stepTau = vr->tau(tauRay,
                                   .5f * stepSize, rng.RandomFloat());
        Tr *= Exp(-stepTau);

        // Possibly terminate ray marching if transmittance is small
        if (Tr.y() < 1e-3) {
            const float continueProb = .5f;
            if (rng.RandomFloat() > continueProb) {
                Tr = 0.f;
                break;
            }
            Tr /= continueProb;
        }

        // Compute single-scattering source term at _p_
        Lv += Tr * vr->Lve(p, w, ray.time);
        Spectrum ss = vr->Sigma_s(p, w, ray.time);
        if (!ss.IsBlack() && scene->lights.size() > 0) {
            int nLights = scene->lights.size();
            int ln = min(Floor2Int(lightNum[sampOffset] * nLights),
                         nLights-1);
            Light *light = scene->lights[ln];
            // Add contribution of _light_ due to scattering at _p_
            float pdf;
            VisibilityTester vis;
            Vector wo;
            LightSample ls(lightComp[sampOffset], lightPos[2*sampOffset],
                           lightPos[2*sampOffset+1]);
            Spectrum L = light->Sample_L(p, 0.f, ls, ray.time, &wo, &pdf, &vis);
            if (!L.IsBlack() && pdf > 0.f && vis.Unoccluded(scene)) {
                Spectrum Ld = L * vis.Transmittance(scene, renderer, NULL, rng, arena);
                Lv += Tr * ss * vr->p(p, w, -wo, ray.time) * Ld * float(nLights) /
                        pdf;
            }
        }
        ++sampOffset;
    }
    *T = Tr;
    return Lv * step;
}