// Integrator Utility Functions
Spectrum UniformSampleAllLights(const Scene *scene,
        const Renderer *renderer, MemoryArena &arena, const Point &p,
        const Normal &n, const Vector &wo, float rayEpsilon,
        float time, BSDF *bsdf, const Sample *sample, RNG &rng,
        const LightSampleOffsets *lightSampleOffsets,
        const BSDFSampleOffsets *bsdfSampleOffsets) {
    Spectrum L(0.);
    for (uint32_t i = 0; i < scene->lights.size(); ++i) {
        Light *light = scene->lights[i];
        int nSamples = lightSampleOffsets ?
                       lightSampleOffsets[i].nSamples : 1;
        // Estimate direct lighting from _light_ samples
        Spectrum Ld(0.);
        for (int j = 0; j < nSamples; ++j) {
            // Find light and BSDF sample values for direct lighting estimate
            LightSample lightSample;
            BSDFSample bsdfSample;
            if (lightSampleOffsets != NULL && bsdfSampleOffsets != NULL) {
                lightSample = LightSample(sample, lightSampleOffsets[i], j);
                bsdfSample = BSDFSample(sample, bsdfSampleOffsets[i], j);
            }
            else {
                lightSample = LightSample(rng);
                bsdfSample = BSDFSample(rng);
            }
            Ld += EstimateDirect(scene, renderer, arena, light, p, n, wo,
                rayEpsilon, time, bsdf, rng, lightSample, bsdfSample,
                BxDFType(BSDF_ALL & ~BSDF_SPECULAR));
        }
        L += Ld / nSamples;
    }
    return L;
}
Beispiel #2
0
// Integrator Utility Functions
Spectrum UniformSampleAllLights(const Interaction &it, const Scene &scene,
                                MemoryArena &arena, Sampler &sampler,
                                const std::vector<int> &nLightSamples,
                                bool handleMedia) {
    ProfilePhase p(Prof::DirectLighting);
    Spectrum L(0.f);
    for (size_t j = 0; j < scene.lights.size(); ++j) {
        // Accumulate contribution of _j_th light to _L_
        const std::shared_ptr<Light> &light = scene.lights[j];
        int nSamples = nLightSamples[j];
        const Point2f *uLightArray = sampler.Get2DArray(nSamples);
        const Point2f *uScatteringArray = sampler.Get2DArray(nSamples);
        if (!uLightArray || !uScatteringArray) {
            // Use a single sample for illumination from _light_
            Point2f uLight = sampler.Get2D();
            Point2f uScattering = sampler.Get2D();
            L += EstimateDirect(it, uScattering, *light, uLight, scene, sampler,
                                arena, handleMedia);
        } else {
            // Estimate direct lighting using sample arrays
            Spectrum Ld(0.f);
            for (int k = 0; k < nSamples; ++k)
                Ld += EstimateDirect(it, uScatteringArray[k], *light,
                                     uLightArray[k], scene, sampler, arena,
                                     handleMedia);
            L += Ld / nSamples;
        }
    }
    return L;
}
Spectrum EstimateDirect(const Scene *scene, const Renderer *renderer,
        MemoryArena &arena, const Light *light, const Point &p,
        const Normal &n, const Vector &wo, float rayEpsilon, float time,
        const BSDF *bsdf, RNG &rng, const LightSample &lightSample,
        const BSDFSample &bsdfSample, BxDFType flags) {
    Spectrum Ld(0.);
    // Sample light source with multiple importance sampling
    Vector wi;
    float lightPdf, bsdfPdf;
    VisibilityTester visibility;
    Spectrum Li = light->Sample_L(p, rayEpsilon, lightSample, time,
                                  &wi, &lightPdf, &visibility);
    if (lightPdf > 0. && !Li.IsBlack()) {
        Spectrum f = bsdf->f(wo, wi, flags);
        if (!f.IsBlack() && visibility.Unoccluded(scene)) {
            // Add light's contribution to reflected radiance
            Li *= visibility.Transmittance(scene, renderer, NULL, rng, arena);
            if (light->IsDeltaLight())
                Ld += f * Li * (AbsDot(wi, n) / lightPdf);
            else {
                bsdfPdf = bsdf->Pdf(wo, wi, flags);
                float weight = PowerHeuristic(1, lightPdf, 1, bsdfPdf);
                Ld += f * Li * (AbsDot(wi, n) * weight / lightPdf);
            }
        }
    }

    // Sample BSDF with multiple importance sampling
    if (!light->IsDeltaLight()) {
        BxDFType sampledType;
        Spectrum f = bsdf->Sample_f(wo, &wi, bsdfSample, &bsdfPdf, flags,
                                    &sampledType);
        if (!f.IsBlack() && bsdfPdf > 0.) {
            float weight = 1.f;
            if (!(sampledType & BSDF_SPECULAR)) {
                lightPdf = light->Pdf(p, wi);
                if (lightPdf == 0.)
                    return Ld;
                weight = PowerHeuristic(1, bsdfPdf, 1, lightPdf);
            }
            // Add light contribution from BSDF sampling
            Intersection lightIsect;
            Spectrum Li(0.f);
            RayDifferential ray(p, wi, rayEpsilon, INFINITY, time);
            if (scene->Intersect(ray, &lightIsect)) {
                if (lightIsect.primitive->GetAreaLight() == light)
                    Li = lightIsect.Le(-wi);
            }
            else
                //Li = light->Le(ray,);
            	Li = Spectrum(0.);
            if (!Li.IsBlack()) {
                Li *= renderer->Transmittance(scene, ray, NULL, rng, arena);
                Ld += f * Li * AbsDot(wi, n) * weight / bsdfPdf;
            }
        }
    }
    return Ld;
}
Beispiel #4
0
void   testList(int testSize) {
   printf("\n  ==== Test %2d. Generate two lists each of size %d by random insertions\n", testID++, testSize);
   List<T> La; randomList(La, testSize); PRINT(La);
   List<T> Lb; randomList(Lb, testSize); PRINT(Lb);

   printf("\n  ==== Test %2d. Call list members by rank (with high complexity)\n", testID++);
   for (int i = 0; i < La.size(); i++) print(La[i]->data); printf("\n");
   for (int i = 0; i < Lb.size(); i++) print(Lb[i]->data); printf("\n");

   printf("\n  ==== Test %2d. Concatenation\n", testID++); PRINT(La); PRINT(Lb);
   while (0 < Lb.size()) La.insertAsLast(Lb.remove(Lb.first())); PRINT(La); PRINT(Lb);

   printf("\n  ==== Test %2d. Increase\n", testID++); PRINT(La);
   increase(La); PRINT(La);

   printf("\n  ==== Test %2d. Copy\n", testID++); PRINT(La);
   List<T> Ld(La); PRINT(Ld);

   printf("\n  ==== Test %2d. Trim by random deletions\n", testID++); PRINT(Ld);
   while (testSize/4 < Ld.size()) {
      int N = rand() % Ld.size(); printf("removing L[%d]=", N);
      ListNodePosi(T) p = Ld.first(); while (0 < N--) p = p->succ;
      print(p->data); printf(" ...\n");
      Ld.remove(p); PRINT(Ld);
   }

   printf("\n  ==== Test %2d. Copy\n", testID++); PRINT(La);
   List<T> Le(La); PRINT(Le);

   printf("\n  ==== Test %2d. FIND in\n", testID++); PRINT(Le);
   for (int i = 0; i <= testSize*2; i++) { //逐一测试[0, 2n]中的所有可能
      ListNodePosi(T) p = Le.find((T) i); printf("Looking for "); print((T)i); printf(": ");
      if (p) { printf(" found with"); print(p->data); }
      else printf(" not found");
      printf("\n");
   } //正确的结构应该是大致(n+1次)失败、(n次)成功相间

   printf("\n  ==== Test %2d. Sort\n", testID++); PRINT(La);
   La.sort(); PRINT(La);

   printf("\n  ==== Test %2d. SEARCH in\n", testID++); PRINT(La);
   for (int i = 0; i <= testSize*2; i++) { //逐一测试[0, 2n]中的所有可能
      ListNodePosi(T) p = La.search((T) i); printf("Looking for "); print((T)i); printf(": ");
      printf(" stopped at"); print(p->data);
      if ((T) i == p->data) printf(" and found");
      printf("\n");
   } //正确的结构应该是大致(n+1次)失败、(n次)成功相间

   printf("\n  ==== Test %2d. Remove redundancy in\n", testID++); PRINT(La);
   printf("%d node(s) removed\n", La.uniquify()); PRINT(La);

   printf("\n  ==== Test %2d. Remove redundancy in\n", testID++); PRINT(Le);
   printf("%d node(s) removed\n", Le.deduplicate()); PRINT(Le);

   printf("\n  ==== Test %2d. Sort\n", testID++); PRINT(Le);
   Le.sort(); PRINT(Le);

   return;
}
glm::vec3 BidirectionalIntegrator::EstimateDirectLight(Intersection &isx, Ray &ray, Geometry* &light)
{
    glm::vec3 Ld(0);

    Ld = MIS_SampleBRDF(isx,ray,light) + MIS_SampleLight(isx,ray,light);

    return Ld;
}
Beispiel #6
0
    Color3f Li(const Scene *scene, Sampler *sampler, const Ray3f &ray) const {
        /* Find the surface that is visible in the requested direction */
        Intersection its;

        //check if the ray intersects the scene
        if (!scene->rayIntersect(ray, its)) {
            //check if a distant disk light is set
            const Emitter* distantsDisk = scene->getDistantEmitter();
            if(distantsDisk == nullptr ) return Color3f(0.0f);

            //sample the distant disk light
            return distantsDisk->sampleL(ray.d);
        }

        //get the radiance of hitten object
        Color3f Le(0.0f, 0.0f, 0.0f);
        if (its.mesh->isEmitter()  ) {
            const Emitter* areaLightEM = its.mesh->getEmitter();
            const areaLight* aEM = static_cast<const areaLight *> (areaLightEM);
            Le = aEM->sampleL(-ray.d, its.shFrame.n, its);
        }

        //get the asigned BSDF
        const BSDF* curBSDF = its.mesh->getBSDF();

        Color3f Ld(0.0f, 0.0f, 0.0f);
        Color3f f(0.0f, 0.0f, 0.0f);
        Color3f totalLight(0.0f, 0.0f, 0.0f);

        //transform to the local frame
        //create a BRDF Query
        BSDFQueryRecord query = BSDFQueryRecord(its.toLocal(-ray.d), Vector3f(0.0f), EMeasure::ESolidAngle);

        //sample the BRDF
        Color3f mats =  curBSDF->sample(query, sampler->next2D());

        if(mats.maxCoeff() > 0.0f) {
            //Check for the light source
            Vector3f wo = its.toWorld(query.wo);
            Ray3f shadowRay(its.p, wo);
            Intersection itsShadow;
            if (scene->rayIntersect(shadowRay, itsShadow)) {
                //intersection check if mesh is emitter
                if(itsShadow.mesh->isEmitter()){
                    Ld = itsShadow.mesh->getEmitter()->radiance();
                }
            } else {
                //check for distant disk light
                const Emitter* distantsDisk = scene->getDistantEmitter();
                if(distantsDisk != nullptr ) Ld = distantsDisk->sampleL(wo);
            }

            totalLight += Ld * mats;
        }

        return Le + totalLight;
    }
Spectrum MetropolisRenderer::Lpath(const Scene *scene,
        const PathVertex *cameraPath, int cameraPathLength,
        MemoryArena &arena, const vector<LightingSample> &samples,
        RNG &rng, float time, const Distribution1D *lightDistribution,
        const RayDifferential &eRay, const Spectrum &eAlpha) const {
    PBRT_MLT_STARTED_LPATH();
    Spectrum L = 0.;
    bool previousSpecular = true, allSpecular = true;
    for (int i = 0; i < cameraPathLength; ++i) {
        // Initialize basic variables for camera path vertex
        const PathVertex &vc = cameraPath[i];
        const Point &pc = vc.bsdf->dgShading.p;
        const Normal &nc = vc.bsdf->dgShading.nn;

        // Add emitted light from vertex if appropriate
        if (previousSpecular && (directLighting == NULL || !allSpecular))
            L += vc.alpha * vc.isect.Le(vc.wPrev);

        // Compute direct illumination for Metropolis path vertex
        Spectrum Ld(0.f);
        if (directLighting == NULL || !allSpecular) {
            // Choose light and call _EstimateDirect()_ for Metropolis vertex
            const LightingSample &ls = samples[i];
            float lightPdf;
            uint32_t lightNum = lightDistribution->SampleDiscrete(ls.lightNum,
                                                                  &lightPdf);
            const Light *light = scene->lights[lightNum];
            PBRT_MLT_STARTED_ESTIMATE_DIRECT();
            
            Ld = vc.alpha *
                 EstimateDirect(scene, this, arena, light, pc, nc, vc.wPrev,
                                vc.isect.rayEpsilon, time, vc.bsdf, rng, NULL,
                                ls.lightSample, ls.bsdfSample,
                                BxDFType(BSDF_ALL & ~BSDF_SPECULAR)) / lightPdf;
            PBRT_MLT_FINISHED_ESTIMATE_DIRECT();
        }
        previousSpecular = vc.specularBounce;
        allSpecular &= previousSpecular;
        L += Ld;
    }
    // Add contribution of escaped ray, if any
    if (!eAlpha.IsBlack() && previousSpecular &&
        (directLighting == NULL || !allSpecular))
        for (uint32_t i = 0; i < scene->lights.size(); ++i)
           L += eAlpha * scene->lights[i]->Le(eRay);
    PBRT_MLT_FINISHED_LPATH();
    return L;
}
Beispiel #8
0
// Integrator Utility Functions
COREDLL Spectrum UniformSampleAllLights(const Scene *scene,
		const Point &p, const Normal &n, const Vector &wo,
		BSDF *bsdf, const Sample *sample,
		int *lightSampleOffset, int *bsdfSampleOffset,
		int *bsdfComponentOffset) {
	Spectrum L(0.);
	for (u_int i = 0; i < scene->lights.size(); ++i) {
		Light *light = scene->lights[i];
		int nSamples = (sample && lightSampleOffset) ?
			sample->n2D[lightSampleOffset[i]] : 1;
		// Estimate direct lighting from _light_ samples
		Spectrum Ld(0.);
		for (int j = 0; j < nSamples; ++j)
			Ld += EstimateDirect(scene, light, p, n, wo, bsdf,
				sample, lightSampleOffset[i], bsdfSampleOffset[i],
				bsdfComponentOffset[i], j);
		L += Ld / nSamples;
	}
	return L;
}
Beispiel #9
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;
}
Beispiel #10
0
    Color3f Li(const Scene *scene, Sampler *sampler, const Ray3f &ray) const {
        /* Find the surface that is visible in the requested direction */
        Intersection its;

        //check if the ray intersects the scene
        if (!scene->rayIntersect(ray, its)) {
            //check if a distant disk light is set
            const Emitter* distantsDisk = scene->getDistantEmitter();
            if(distantsDisk == nullptr ) return Color3f(0.0f);

            //sample the distant disk light
            Vector3f d = ray.d;
            return distantsDisk->sampleL(d);
        }

        //get the Number of lights from the scene
        const  std::vector<Emitter *> lights = scene->getEmitters();
        uint32_t nLights = lights.size();

        Color3f tp(1.0f, 1.0f, 1.0f);
        Color3f L(0.0f, 0.0f, 0.0f);
        Ray3f pathRay(ray.o, ray.d);

        bool deltaFlag = true;

        while(true) {

            if (its.mesh->isEmitter() && deltaFlag) {
                const Emitter* areaLightEM = its.mesh->getEmitter();
                const areaLight* aEM = static_cast<const areaLight *> (areaLightEM);
                L += tp * aEM->sampleL(-pathRay.d, its.shFrame.n, its);
            }

            //Light sampling
            //randomly select a lightsource
            uint32_t var = uint32_t(std::min(sampler->next1D()*nLights, float(nLights) - 1.0f));

            //init the light color
            Color3f Li(0.0f, 0.0f, 0.0f);
            Color3f Ld(1.0f, 1.0f, 1.0f);

            //create a sample for the light
            const BSDF* curBSDF = its.mesh->getBSDF();
            const Point2f lightSample = sampler->next2D();
            VisibilityTester vis;
            Vector3f wo;
            float lightpdf;
            float bsdfpdf;
            Normal3f n = its.shFrame.n;

            deltaFlag = curBSDF->isDeltaBSDF();

            //sample the light

            {
                Li = lights[var]->sampleL(its.p, Epsilon, lightSample , &wo, &lightpdf, &vis);
                lightpdf /= float(nLights);
                //check if the pdf of the sample is greater than 0 and if the color is not black
                if(lightpdf > 0 && Li.maxCoeff() != 0.0f) {
                    //calculate the cosine term wi in my case the vector to the light
                    float cosTerm = std::abs(n.dot(wo));
                    const BSDFQueryRecord queryEM = BSDFQueryRecord(its.toLocal(- pathRay.d), its.toLocal(wo), EMeasure::ESolidAngle, sampler);
                    Color3f f = curBSDF->eval(queryEM);

                    if(f.maxCoeff() > 0.0f && f.minCoeff() >= 0.0f && vis.Unoccluded(scene)) {
                        bsdfpdf = curBSDF->pdf(queryEM);
                        float weight = BalanceHeuristic(float(1), lightpdf, float(1), bsdfpdf);
                        if(curBSDF->isDeltaBSDF())  weight = 1.0f;
                        if(bsdfpdf > 0.0f) {
                            Ld = (weight * f * Li * cosTerm) / lightpdf;
                            L += tp * Ld;
                        } else {
                            //cout << "bsdfpdf = " << bsdfpdf  << endl;
                            //cout << "f = " << f  << endl;
                        }
                    }
                }
            }

            //Material part
            BSDFQueryRecord queryMats = BSDFQueryRecord(its.toLocal(-pathRay.d), Vector3f(0.0f), EMeasure::ESolidAngle, sampler);

            Color3f fi =  curBSDF->sample(queryMats, sampler->next2D());
            bsdfpdf = curBSDF->pdf(queryMats);
            lightpdf = 0.0f;
            if(fi.maxCoeff() > 0.0f && fi.minCoeff() >= 0.0f) {
                if(bsdfpdf > 0.0f) {
                    Ray3f shadowRay(its.p, its.toWorld(queryMats.wo));
                    Intersection lightIsect;

                     if (scene->rayIntersect(shadowRay, lightIsect)) {
                         if(lightIsect.mesh->isEmitter()){
                            const Emitter* areaLightEMcur = lightIsect.mesh->getEmitter();
                            const areaLight* aEMcur = static_cast<const areaLight *> (areaLightEMcur);

                            Li = aEMcur->sampleL(-shadowRay.d, lightIsect.shFrame.n, lightIsect);
                            lightpdf = aEMcur->pdf(its.p, (lightIsect.p - its.p).normalized(), lightIsect.p, Normal3f(lightIsect.shFrame.n));
                         }
                     } else {
                         const Emitter* distantsDisk = scene->getDistantEmitter();
                         if(distantsDisk != nullptr ) {
                             //check if THIS is right!
                             Li = distantsDisk->sampleL(lightIsect.toWorld(queryMats.wo));
                             lightpdf = distantsDisk->pdf(Point3f(0.0f), wo, Point3f(0.0f), Normal3f(0.0f));
                         }
                     }
                     lightpdf /= float(nLights);
                     //calculate the weights
                     float weight = BalanceHeuristic(float(1), bsdfpdf, float(1), lightpdf);


                     //check if the lightcolor is not black
                     if(Li.maxCoeff() > 0.0f  && lightpdf > 0.0f ) {
                         //wo in my case the vector to the light
                         Ld = weight * Li * fi;
                         L += tp * Ld;
                     }
                }



                 tp *= fi;
            } else {
                break;
            }

            wo = its.toWorld(queryMats.wo);
            pathRay = Ray3f(its.p, wo);

            if (!scene->rayIntersect(pathRay, its)) {
                const Emitter* distantsDisk = scene->getDistantEmitter();
                if(distantsDisk != nullptr ) {
                    //sample the distant disk light
                    Vector3f d = pathRay.d;
                    L += tp * distantsDisk->sampleL(d);
                }


                break;
            }

            float maxCoeff = tp.maxCoeff();
            float q = std::min(0.99f, maxCoeff);
            if(q < sampler->next1D()){
                break;
            }
            tp /= q;
        }

        return L;

    }
Spectrum MetropolisRenderer::Lbidir(const Scene *scene,
        const PathVertex *cameraPath, int cameraPathLength,
        const PathVertex *lightPath, int lightPathLength,
        MemoryArena &arena, const vector<LightingSample> &samples,
        RNG &rng, float time, const Distribution1D *lightDistribution,
        const RayDifferential &eRay, const Spectrum &eAlpha) const {
    PBRT_MLT_STARTED_LBIDIR();
    Spectrum L = 0.;
    bool previousSpecular = true, allSpecular = true;
    // Compute number of specular vertices for each path length
    int nVerts = cameraPathLength + lightPathLength + 2;
    int *nSpecularVertices = ALLOCA(int, nVerts);
    memset(nSpecularVertices, 0, nVerts * sizeof(int));
    for (int i = 0; i < cameraPathLength; ++i)
        for (int j = 0; j < lightPathLength; ++j)
            if (cameraPath[i].specularBounce || lightPath[j].specularBounce)
                ++nSpecularVertices[i+j+2];
    for (int i = 0; i < cameraPathLength; ++i) {
        // Initialize basic variables for camera path vertex
        const PathVertex &vc = cameraPath[i];
        const Point &pc = vc.bsdf->dgShading.p;
        const Normal &nc = vc.bsdf->dgShading.nn;

        // Compute reflected light at camera path vertex

        // Add emitted light from vertex if appropriate
        if (previousSpecular && (directLighting == NULL || !allSpecular))
            L += vc.alpha * vc.isect.Le(vc.wPrev);

        // Compute direct illumination for Metropolis path vertex
        Spectrum Ld(0.f);
        if (directLighting == NULL || !allSpecular) {
            // Choose light and call _EstimateDirect()_ for Metropolis vertex
            const LightingSample &ls = samples[i];
            float lightPdf;
            uint32_t lightNum = lightDistribution->SampleDiscrete(ls.lightNum,
                                                                  &lightPdf);
            const Light *light = scene->lights[lightNum];
            PBRT_MLT_STARTED_ESTIMATE_DIRECT();
            
            Ld = vc.alpha *
                 EstimateDirect(scene, this, arena, light, pc, nc, vc.wPrev,
                                vc.isect.rayEpsilon, time, vc.bsdf, rng, NULL,
                                ls.lightSample, ls.bsdfSample,
                                BxDFType(BSDF_ALL & ~BSDF_SPECULAR)) / lightPdf;
            PBRT_MLT_FINISHED_ESTIMATE_DIRECT();
        }
        previousSpecular = vc.specularBounce;
        allSpecular &= previousSpecular;
        L += Ld / (i + 1 - nSpecularVertices[i+1]);
        if (!vc.specularBounce) {
            // Loop over light path vertices and connect to camera vertex
            for (int j = 0; j < lightPathLength; ++j) {
                const PathVertex &vl = lightPath[j];
                const Point &pl = vl.bsdf->dgShading.p;
                const Normal &nl = vl.bsdf->dgShading.nn;
                if (!vl.specularBounce) {
                    // Compute contribution between camera and light vertices
                    Vector w = Normalize(pl - pc);
                    Spectrum fc = vc.bsdf->f(vc.wPrev, w) * (1 + vc.nSpecularComponents);
                    Spectrum fl = vl.bsdf->f(-w, vl.wPrev) * (1 + vl.nSpecularComponents);
                    if (fc.IsBlack() || fl.IsBlack()) continue;
                    Ray r(pc, pl - pc, 1e-3f, .999f, time);
                    if (!scene->IntersectP(r)) {
                        // Compute weight for bidirectional path, _pathWt_
                        float pathWt = 1.f / (i + j + 2 - nSpecularVertices[i+j+2]);
                        float G = AbsDot(nc, w) * AbsDot(nl, w) / DistanceSquared(pl, pc);
                        L += (vc.alpha * fc * G * fl * vl.alpha) * pathWt;
                    }
                }
            }
        }
    }
    // Add contribution of escaped ray, if any
    if (!eAlpha.IsBlack() && previousSpecular &&
        (directLighting == NULL || !allSpecular))
        for (uint32_t i = 0; i < scene->lights.size(); ++i)
           L += eAlpha * scene->lights[i]->Le(eRay);
    PBRT_MLT_FINISHED_LBIDIR();
    return L;
}
Beispiel #12
0
Spectrum EstimateDirect(const Interaction &it, const Point2f &uScattering,
                        const Light &light, const Point2f &uLight,
                        const Scene &scene, Sampler &sampler,
                        MemoryArena &arena, bool handleMedia, bool specular) {
    BxDFType bsdfFlags =
        specular ? BSDF_ALL : BxDFType(BSDF_ALL & ~BSDF_SPECULAR);
    Spectrum Ld(0.f);
    // Sample light source with multiple importance sampling
    Vector3f wi;
    Float lightPdf = 0, scatteringPdf = 0;
    VisibilityTester visibility;
    Spectrum Li = light.Sample_Li(it, uLight, &wi, &lightPdf, &visibility);
    if (lightPdf > 0 && !Li.IsBlack()) {
        // Compute BSDF or phase function's value for light sample
        Spectrum f;
        if (it.IsSurfaceInteraction()) {
            // Evaluate BSDF for light sampling strategy
            const SurfaceInteraction &isect = (const SurfaceInteraction &)it;
            f = isect.bsdf->f(isect.wo, wi, bsdfFlags) *
                AbsDot(wi, isect.shading.n);
            scatteringPdf = isect.bsdf->Pdf(isect.wo, wi, bsdfFlags);
        } else {
            // Evaluate phase function for light sampling strategy
            const MediumInteraction &mi = (const MediumInteraction &)it;
            Float p = mi.phase->p(mi.wo, wi);
            f = Spectrum(p);
            scatteringPdf = p;
        }
        if (!f.IsBlack()) {
            // Compute effect of visibility for light source sample
            if (handleMedia)
                Li *= visibility.Tr(scene, sampler);
            else if (!visibility.Unoccluded(scene))
                Li = Spectrum(0.f);

            // Add light's contribution to reflected radiance
            if (!Li.IsBlack()) {
                if (IsDeltaLight(light.flags))
                    Ld += f * Li / lightPdf;
                else {
                    Float weight =
                        PowerHeuristic(1, lightPdf, 1, scatteringPdf);
                    Ld += f * Li * weight / lightPdf;
                }
            }
        }
    }

    // Sample BSDF with multiple importance sampling
    if (!IsDeltaLight(light.flags)) {
        Spectrum f;
        bool sampledSpecular = false;
        if (it.IsSurfaceInteraction()) {
            // Sample scattered direction for surface interactions
            BxDFType sampledType;
            const SurfaceInteraction &isect = (const SurfaceInteraction &)it;
            f = isect.bsdf->Sample_f(isect.wo, &wi, uScattering, &scatteringPdf,
                                     bsdfFlags, &sampledType);
            f *= AbsDot(wi, isect.shading.n);
            sampledSpecular = sampledType & BSDF_SPECULAR;
        } else {
            // Sample scattered direction for medium interactions
            const MediumInteraction &mi = (const MediumInteraction &)it;
            Float p = mi.phase->Sample_p(mi.wo, &wi, uScattering);
            f = Spectrum(p);
            scatteringPdf = p;
        }
        if (!f.IsBlack() && scatteringPdf > 0) {
            // Account for light contributions along sampled direction _wi_
            Float weight = 1;
            if (!sampledSpecular) {
                lightPdf = light.Pdf_Li(it, wi);
                if (lightPdf == 0) return Ld;
                weight = PowerHeuristic(1, scatteringPdf, 1, lightPdf);
            }

            // Find intersection and compute transmittance
            SurfaceInteraction lightIsect;
            Ray ray = it.SpawnRay(wi);
            Spectrum Tr(1.f);
            bool foundSurfaceInteraction =
                handleMedia ? scene.IntersectTr(ray, sampler, &lightIsect, &Tr)
                            : scene.Intersect(ray, &lightIsect);

            // Add light contribution from material sampling
            Spectrum Li(0.f);
            if (foundSurfaceInteraction) {
                if (lightIsect.primitive->GetAreaLight() == &light)
                    Li = lightIsect.Le(-wi);
            } else
                Li = light.Le(ray);
            if (!Li.IsBlack()) Ld += f * Li * Tr * weight / scatteringPdf;
        }
    }
    return Ld;
}
Spectrum EstimateDirect(const Scene *scene,
        const Light *light, const Point &p,
		const Normal &n, const Vector &wo,
		BSDF *bsdf, const Sample *sample, int lightSamp,
		int bsdfSamp, int bsdfComponent, u_int sampleNum) {
	Spectrum Ld(0.);
	// Find light and BSDF sample values for direct lighting estimate
	float ls1, ls2, bs1, bs2, bcs;
	if (lightSamp != -1 && bsdfSamp != -1 &&
		sampleNum < sample->n2D[lightSamp] &&
		sampleNum < sample->n2D[bsdfSamp]) {
		ls1 = sample->twoD[lightSamp][2*sampleNum];
		ls2 = sample->twoD[lightSamp][2*sampleNum+1];
		bs1 = sample->twoD[bsdfSamp][2*sampleNum];
		bs2 = sample->twoD[bsdfSamp][2*sampleNum+1];
		bcs = sample->oneD[bsdfComponent][sampleNum];
	}
	else {
		ls1 = RandomFloat();
		ls2 = RandomFloat();
		bs1 = RandomFloat();
		bs2 = RandomFloat();
		bcs = RandomFloat();
	}
	// Sample light source with multiple importance sampling
	Vector wi;
	float lightPdf, bsdfPdf;
	VisibilityTester visibility;
	Spectrum Li = light->Sample_L(p, n,
		ls1, ls2, &wi, &lightPdf, &visibility);
	if (lightPdf > 0. && !Li.Black()) {
		Spectrum f = bsdf->f(wo, wi);
		if (!f.Black() && visibility.Unoccluded(scene)) {
			// Add light's contribution to reflected radiance
			Li *= visibility.Transmittance(scene);
			if (light->IsDeltaLight())
				Ld += f * Li * AbsDot(wi, n) / lightPdf;
			else {
				bsdfPdf = bsdf->Pdf(wo, wi);
				float weight = PowerHeuristic(1, lightPdf, 1, bsdfPdf);
				Ld += f * Li * AbsDot(wi, n) * weight / lightPdf;
			}
		}
	}
	// Sample BSDF with multiple importance sampling
	if (!light->IsDeltaLight()) {
		BxDFType flags = BxDFType(BSDF_ALL & ~BSDF_SPECULAR);
		Spectrum f = bsdf->Sample_f(wo, &wi,
			bs1, bs2, bcs, &bsdfPdf, flags);
		if (!f.Black() && bsdfPdf > 0.) {
			lightPdf = light->Pdf(p, n, wi);
			if (lightPdf > 0.) {
				// Add light contribution from BSDF sampling
				float weight = PowerHeuristic(1, bsdfPdf, 1, lightPdf);
				Intersection lightIsect;
				Spectrum Li(0.f);
				RayDifferential ray(p, wi);
				if (scene->Intersect(ray, &lightIsect)) {
					if (lightIsect.primitive->GetAreaLight() == light)
						Li = lightIsect.Le(-wi);
				}
				else
					Li = light->Le(ray);
				if (!Li.Black()) {
					Li *= scene->Transmittance(ray);
					Ld += f * Li * AbsDot(wi, n) * weight / bsdfPdf;
				}
			}
		}
	}
	return Ld;
}