示例#1
0
文件: light.cpp 项目: AI42/OM3D
void Light::SHProject(const PbrtPoint &p, float pEpsilon, int lmax,
        const Scene *scene, bool computeLightVisibility, float time,
        RNG &rng, Spectrum *coeffs) const {
    for (int i = 0; i < SHTerms(lmax); ++i)
        coeffs[i] = 0.f;
    uint32_t ns = RoundUpPow2(nSamples);
    uint32_t scramble1D = rng.RandomUInt();
    uint32_t scramble2D[2] = { rng.RandomUInt(), rng.RandomUInt() };
    float *Ylm = ALLOCA(float, SHTerms(lmax));
    for (uint32_t i = 0; i < ns; ++i) {
        // Compute incident radiance sample from _light_, update SH _coeffs_
        float u[2], pdf;
        Sample02(i, scramble2D, u);
        LightSample lightSample(u[0], u[1], VanDerCorput(i, scramble1D));
        Vector wi;
        VisibilityTester vis;
        Spectrum Li = Sample_L(p, pEpsilon, lightSample, time, &wi, &pdf, &vis);
        if (!Li.IsBlack() && pdf > 0.f &&
            (!computeLightVisibility || vis.Unoccluded(scene))) {
            // Add light sample contribution to MC estimate of SH coefficients
            SHEvaluate(wi, lmax, Ylm);
            for (int j = 0; j < SHTerms(lmax); ++j)
                coeffs[j] += Li * Ylm[j] / (pdf * ns);
        }
    }
}
示例#2
0
void AggregateTest::Render(const Scene *scene) {
    RNG rng;
    ProgressReporter prog(nIterations, "Aggregate Test");
    // Compute bounding box of region used to generate random rays
    BBox bbox = scene->WorldBound();
    bbox.Expand(bbox.pMax[bbox.MaximumExtent()] -
                bbox.pMin[bbox.MaximumExtent()]);
    Point lastHit;
    float lastEps = 0.f;
    for (int i = 0; i < nIterations; ++i) {
        // Choose random rays, _rayAccel_ and _rayAll_ for testing

        // Choose ray origin for testing accelerator
        Point org(Lerp(rng.RandomFloat(), bbox.pMin.x, bbox.pMax.x),
                  Lerp(rng.RandomFloat(), bbox.pMin.y, bbox.pMax.y),
                  Lerp(rng.RandomFloat(), bbox.pMin.z, bbox.pMax.z));
        if ((rng.RandomUInt() % 4) == 0) org = lastHit;

        // Choose ray direction for testing accelerator
        Vector dir = UniformSampleSphere(rng.RandomFloat(), rng.RandomFloat());
        if ((rng.RandomUInt() % 32) == 0) dir.x = dir.y = 0.f;
        else if ((rng.RandomUInt() % 32) == 0) dir.x = dir.z = 0.f;
        else if ((rng.RandomUInt() % 32) == 0) dir.y = dir.z = 0.f;

        // Choose ray epsilon for testing accelerator
        float eps = 0.f;
        if (rng.RandomFloat() < .25) eps = lastEps;
        else if (rng.RandomFloat() < .25) eps = 1e-3f;
        Ray rayAccel(org, dir, eps);
        Ray rayAll = rayAccel;

        // Compute intersections using accelerator and exhaustive testing
        Intersection isectAccel, isectAll;
        bool hitAccel = scene->Intersect(rayAccel, &isectAccel);
        bool hitAll = false;
        bool inconsistentBounds = false;
        for (u_int j = 0; j < primitives.size(); ++j) {
            if (bboxes[j].IntersectP(rayAll))
                hitAll |= primitives[j]->Intersect(rayAll, &isectAll);
            else if (primitives[j]->Intersect(rayAll, &isectAll))
                inconsistentBounds = true;
        }

        // Report any inconsistencies between intersections
        if (!inconsistentBounds &&
            ((hitAccel != hitAll) || (rayAccel.maxt != rayAll.maxt)))
            Warning("Disagreement: t accel %.16g [%a] t exhaustive %.16g [%a]\n"
                    "Ray: org [%a, %a, %a], dir [%a, %a, %a], mint = %a",
                    rayAccel.maxt, rayAll.maxt, rayAccel.maxt, rayAll.maxt,
                    rayAll.o.x, rayAll.o.y, rayAll.o.z,
                    rayAll.d.x, rayAll.d.y, rayAll.d.z, rayAll.mint);
        if (hitAll) {
            lastHit = rayAll(rayAll.maxt);
            lastEps = isectAll.RayEpsilon;
        }
        prog.Update();
    }
    prog.Done();
}
示例#3
0
Spectrum IrradianceCacheIntegrator::indirectLo(const Point &p,
        const Normal &ng, float pixelSpacing, const Vector &wo,
        float rayEpsilon, BSDF *bsdf, BxDFType flags, RNG &rng,
        const Scene *scene, const Renderer *renderer,
        MemoryArena &arena) const {
    if (bsdf->NumComponents(flags) == 0)
        return Spectrum(0.);
    Spectrum E;
    Vector wi;
    // Get irradiance _E_ and average incident direction _wi_ at point _p_
    if (!interpolateE(scene, p, ng, &E, &wi)) {
        // Compute irradiance at current point
        PBRT_IRRADIANCE_CACHE_STARTED_COMPUTING_IRRADIANCE(const_cast<Point *>(&p), const_cast<Normal *>(&ng));
        uint32_t scramble[2] = { rng.RandomUInt(), rng.RandomUInt() };
        float minHitDistance = INFINITY;
        Vector wAvg(0,0,0);
        Spectrum LiSum = 0.f;
        for (int i = 0; i < nSamples; ++i) {
            // Sample direction for irradiance estimate ray
            float u[2];
            Sample02(i, scramble, u);
            Vector w = CosineSampleHemisphere(u[0], u[1]);
            RayDifferential r(p, bsdf->LocalToWorld(w), rayEpsilon);
            r.d = Faceforward(r.d, ng);

            // Trace ray to sample radiance for irradiance estimate
            PBRT_IRRADIANCE_CACHE_STARTED_RAY(&r);
            Spectrum L = pathL(r, scene, renderer, rng, arena);
            LiSum += L;
            wAvg += r.d * L.y();
            minHitDistance = min(minHitDistance, r.maxt);
            PBRT_IRRADIANCE_CACHE_FINISHED_RAY(&r, r.maxt, &L);
        }
        E = (M_PI / float(nSamples)) * LiSum;
        PBRT_IRRADIANCE_CACHE_FINISHED_COMPUTING_IRRADIANCE(const_cast<Point *>(&p), const_cast<Normal *>(&ng));

        // Add computed irradiance value to cache

        // Compute irradiance sample's contribution extent and bounding box
        float maxDist = maxSamplePixelSpacing * pixelSpacing;
        float minDist = minSamplePixelSpacing * pixelSpacing;
        float contribExtent = Clamp(minHitDistance / 2.f, minDist, maxDist);
        BBox sampleExtent(p);
        sampleExtent.Expand(contribExtent);
        PBRT_IRRADIANCE_CACHE_ADDED_NEW_SAMPLE(const_cast<Point *>(&p), const_cast<Normal *>(&ng), contribExtent, &E, &wAvg, pixelSpacing);

        // Allocate _IrradianceSample_, get write lock, add to octree
        IrradianceSample *sample = new IrradianceSample(E, p, ng, wAvg,
                                                        contribExtent);
        RWMutexLock lock(*mutex, WRITE);
        octree->Add(sample, sampleExtent);
        wi = wAvg;
    }

    // Compute reflected radiance due to irradiance and BSDF
    if (wi.LengthSquared() == 0.f) return Spectrum(0.);
    return bsdf->f(wo, Normalize(wi), flags) * E;
}
// AmbientOcclusionIntegrator Method Definitions
Spectrum AmbientOcclusionIntegrator::Li(const Scene *scene, const Renderer *renderer,
        const RayDifferential &ray, const Intersection &isect,
        const Sample *sample, RNG &rng, MemoryArena &arena, int wavelength) const {

    BSDF *bsdf = isect.GetBSDF(ray, arena, wavelength);
    const Point &p = bsdf->dgShading.p;
    Normal n = Faceforward(isect.dg.nn, -ray.d);

    uint32_t scramble[2] = { rng.RandomUInt(), rng.RandomUInt() };
    float u[2];
    int nClear = 0;
    for (int i = 0; i < nSamples; ++i) {
        Sample02(i, scramble, u);
        Vector w = UniformSampleSphere(u[0], u[1]);
        if (Dot(w, n) < 0.) w = -w;
        Ray r(p, w, .01f, maxDist);
        if (!scene->IntersectP(r)) ++nClear;
    }
    return Spectrum(float(nClear) / float(nSamples));
}
示例#5
0
void LatinHypercube(float *samples, u_int nSamples, u_int nDim, RNG &rng) {
    // Generate LHS samples along diagonal
    float delta = 1.f / nSamples;
    for (u_int i = 0; i < nSamples; ++i)
        for (u_int j = 0; j < nDim; ++j)
            samples[nDim * i + j] = (i + (rng.RandomFloat())) * delta;

    // Permute LHS samples in each dimension
    for (u_int i = 0; i < nDim; ++i) {
        for (u_int j = 0; j < nSamples; ++j) {
            u_int other = j + (rng.RandomUInt() % (nSamples - j));
            swap(samples[nDim * j + i], samples[nDim * other + i]);
        }
    }
}
void DipoleSubsurfaceIntegrator::Preprocess(const Scene *scene,
        const Camera *camera, const Renderer *renderer) {
    if (scene->lights.size() == 0) return;
    vector<SurfacePoint> pts;
    // Get _SurfacePoint_s for translucent objects in scene
    if (filename != "") {
        // Initialize _SurfacePoint_s from file
        vector<float> fpts;
        if (ReadFloatFile(filename.c_str(), &fpts)) {
            if ((fpts.size() % 8) != 0)
                Error("Excess values (%d) in points file \"%s\"", int(fpts.size() % 8),
                      filename.c_str());
            for (u_int i = 0; i < fpts.size(); i += 8)
                pts.push_back(SurfacePoint(Point(fpts[i], fpts[i+1], fpts[i+2]),
                                           Normal(fpts[i+3], fpts[i+4], fpts[i+5]),
                                           fpts[i+6], fpts[i+7]));
        }
    }
    if (pts.size() == 0) {
        Point pCamera = camera->CameraToWorld(camera->shutterOpen,
                                              Point(0, 0, 0));
        FindPoissonPointDistribution(pCamera, camera->shutterOpen,
                                     minSampleDist, scene, &pts);
    }

    // Compute irradiance values at sample points
    RNG rng;
    MemoryArena arena;
    PBRT_SUBSURFACE_STARTED_COMPUTING_IRRADIANCE_VALUES();
    ProgressReporter progress(pts.size(), "Computing Irradiances");
    for (uint32_t i = 0; i < pts.size(); ++i) {
        SurfacePoint &sp = pts[i];
        Spectrum E(0.f);
        for (uint32_t j = 0; j < scene->lights.size(); ++j) {
            // Add irradiance from light at point
            const Light *light = scene->lights[j];
            Spectrum Elight = 0.f;
            int nSamples = RoundUpPow2(light->nSamples);
            uint32_t scramble[2] = { rng.RandomUInt(), rng.RandomUInt() };
            uint32_t compScramble = rng.RandomUInt();
            for (int s = 0; s < nSamples; ++s) {
                float lpos[2];
                Sample02(s, scramble, lpos);
                float lcomp = VanDerCorput(s, compScramble);
                LightSample ls(lpos[0], lpos[1], lcomp);
                Vector wi;
                float lightPdf;
                VisibilityTester visibility;
                Spectrum Li = light->Sample_L(sp.p, sp.rayEpsilon,
                    ls, camera->shutterOpen, &wi, &lightPdf, &visibility);
                if (Dot(wi, sp.n) <= 0.) continue;
                if (Li.IsBlack() || lightPdf == 0.f) continue;
                Li *= visibility.Transmittance(scene, renderer, NULL, rng, arena);
                if (visibility.Unoccluded(scene))
                    Elight += Li * AbsDot(wi, sp.n) / lightPdf;
            }
            E += Elight / nSamples;
        }
        if (E.y() > 0.f)
        {
            irradiancePoints.push_back(IrradiancePoint(sp, E));
            PBRT_SUBSURFACE_COMPUTED_IRRADIANCE_AT_POINT(&sp, &E);
        }
        arena.FreeAll();
        progress.Update();
    }
    progress.Done();
    PBRT_SUBSURFACE_FINISHED_COMPUTING_IRRADIANCE_VALUES();

    // Create octree of clustered irradiance samples
    octree = octreeArena.Alloc<SubsurfaceOctreeNode>();
    for (uint32_t i = 0; i < irradiancePoints.size(); ++i)
        octreeBounds = Union(octreeBounds, irradiancePoints[i].p);
    for (uint32_t i = 0; i < irradiancePoints.size(); ++i)
        octree->Insert(octreeBounds, &irradiancePoints[i], octreeArena);
    octree->InitHierarchy();
}