Пример #1
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;
}
Пример #2
0
Spectrum UniformSampleOneLight(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, int lightNumOffset,
        const LightSampleOffsets *lightSampleOffset,
        const BSDFSampleOffsets *bsdfSampleOffset) {
    // Randomly choose a single light to sample, _light_
    int nLights = int(scene->lights.size());
    if (nLights == 0) return Spectrum(0.);
    int lightNum;
    if (lightNumOffset != -1)
        lightNum = Floor2Int(sample->oneD[lightNumOffset][0] * nLights);
    else
        lightNum = Floor2Int(rng.RandomFloat() * nLights);
    lightNum = min(lightNum, nLights-1);
    Light *light = scene->lights[lightNum];

    // Initialize light and bsdf samples for single light sample
    LightSample lightSample;
    BSDFSample bsdfSample;
    if (lightSampleOffset != NULL && bsdfSampleOffset != NULL) {
        lightSample = LightSample(sample, *lightSampleOffset, 0);
        bsdfSample = BSDFSample(sample, *bsdfSampleOffset, 0);
    }
    else {
        lightSample = LightSample(rng);
        bsdfSample = BSDFSample(rng);
    }
    return (float)nLights *
        EstimateDirect(scene, renderer, arena, light, p, n, wo,
                       rayEpsilon, time, bsdf, rng, lightSample,
                       bsdfSample, BxDFType(BSDF_ALL & ~BSDF_SPECULAR));
}
Пример #3
0
// 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;
}
Пример #4
0
static Spectrum L(const Scene *scene, const Renderer *renderer,
        const Camera *camera, MemoryArena &arena, RNG &rng, int maxDepth,
        bool ignoreDirect, const MLTSample &sample) {
    // Generate camera ray from Metropolis sample
    RayDifferential ray;
    float cameraWeight = camera->GenerateRayDifferential(sample.cameraSample,
                                                         &ray);
    Spectrum pathThroughput = cameraWeight, L = 0.;
    bool specularBounce = false, allSpecular = true;
    for (int pathLength = 0; pathLength < maxDepth; ++pathLength) {
        // Find next intersection in Metropolis light path
        Intersection isect;
        if (!scene->Intersect(ray, &isect)) {
            bool includeLe = ignoreDirect ? (specularBounce && !allSpecular) :
                                            (pathLength == 0 || specularBounce);
            if (includeLe)
                for (uint32_t i = 0; i < scene->lights.size(); ++i)
                   L += pathThroughput * scene->lights[i]->Le(ray);
            break;
        }
        if (ignoreDirect ? (specularBounce && !allSpecular) :
                           (specularBounce || pathLength == 0))
            L += pathThroughput * isect.Le(-ray.d);
        BSDF *bsdf = isect.GetBSDF(ray, arena);
        const Point &p = bsdf->dgShading.p;
        const Normal &n = bsdf->dgShading.nn;
        Vector wo = -ray.d;
        const PathSample &ps = sample.pathSamples[pathLength];
        // Sample direct illumination for Metropolis path vertex
        if (!ignoreDirect || pathLength > 0) {
            LightSample lightSample(ps.lightDir0, ps.lightDir1, ps.lightNum0);
            BSDFSample bsdfSample(ps.bsdfLightDir0, ps.bsdfLightDir1,
                                  ps.bsdfLightComponent);
            uint32_t lightNum = Floor2Int(ps.lightNum1 * scene->lights.size());
            lightNum = min(lightNum, (uint32_t)(scene->lights.size()-1));
            const Light *light = scene->lights[lightNum];
            L += pathThroughput *
                 EstimateDirect(scene, renderer, arena, light, p, n, wo,
                     isect.rayEpsilon, sample.cameraSample.time, bsdf, rng,
                     lightSample, bsdfSample);
        }

        // Sample direction for outgoing Metropolis path direction
        BSDFSample outgoingBSDFSample(ps.bsdfDir0, ps.bsdfDir1,
                                      ps.bsdfComponent);
        Vector wi;
        float pdf;
        BxDFType flags;
        Spectrum f = bsdf->Sample_f(wo, &wi, outgoingBSDFSample,
                                    &pdf, BSDF_ALL, &flags);
        if (f.IsBlack() || pdf == 0.)
            break;
        specularBounce = (flags & BSDF_SPECULAR) != 0;
        allSpecular &= specularBounce;
        pathThroughput *= f * AbsDot(wi, n) / pdf;
        ray = RayDifferential(p, wi, ray, isect.rayEpsilon);
        //pathThroughput *= renderer->Transmittance(scene, ray, NULL, rng, arena);
    }
    return L;
}
Пример #5
0
COREDLL Spectrum WeightedSampleOneLight(const Scene *scene,
		const Point &p, const Normal &n,
		const Vector &wo, BSDF *bsdf,
		const Sample *sample, int lightSampleOffset,
		int lightNumOffset, int bsdfSampleOffset,
		int bsdfComponentOffset, float *&avgY,
		float *&avgYsample, float *&cdf,
		float &overallAvgY) {
	int nLights = int(scene->lights.size());
	// Initialize _avgY_ array if necessary
	if (!avgY) {
		avgY = new float[nLights];
		avgYsample = new float[nLights];
		cdf = new float[nLights+1];
		for (int i = 0; i < nLights; ++i)
			avgY[i] = avgYsample[i] = 0.;
	}
	Spectrum L(0.);
	if (overallAvgY == 0.) {
		// Sample one light uniformly and initialize luminance arrays
		L = UniformSampleOneLight(scene, p, n,
		    wo, bsdf, sample, lightSampleOffset,
			lightNumOffset, bsdfSampleOffset,
			bsdfComponentOffset);
		float luminance = L.y();
		overallAvgY = luminance;
		for (int i = 0; i < nLights; ++i)
			avgY[i] = luminance;
	}
	else {
		// Choose _light_ according to average reflected luminance
		float c, lightSampleWeight;
		for (int i = 0; i < nLights; ++i)
			avgYsample[i] = max(avgY[i], .1f * overallAvgY);
		ComputeStep1dCDF(avgYsample, nLights, &c, cdf);
		float t = SampleStep1d(avgYsample, cdf, c, nLights,
			sample->oneD[lightNumOffset][0], &lightSampleWeight);
		int lightNum = min(Float2Int(nLights * t), nLights-1);
		Light *light = scene->lights[lightNum];
		L = EstimateDirect(scene, light, p, n, wo, bsdf,
			sample, lightSampleOffset, bsdfSampleOffset,
			bsdfComponentOffset, 0);
		// Update _avgY_ array with reflected radiance due to light
		float luminance = L.y();
		avgY[lightNum] =
			ExponentialAverage(avgY[lightNum], luminance, .99f);
		overallAvgY =
			ExponentialAverage(overallAvgY, luminance, .999f);
		L /= lightSampleWeight;
	}
	return L;
}
Пример #6
0
Spectrum UniformSampleOneLight(const Interaction &it, const Scene &scene,
                               MemoryArena &arena, Sampler &sampler,
                               bool handleMedia) {
    ProfilePhase p(Prof::DirectLighting);
    // Randomly choose a single light to sample, _light_
    int nLights = int(scene.lights.size());
    if (nLights == 0) return Spectrum(0.f);
    int lightNum = std::min((int)(sampler.Get1D() * nLights), nLights - 1);
    const std::shared_ptr<Light> &light = scene.lights[lightNum];
    Point2f uLight = sampler.Get2D();
    Point2f uScattering = sampler.Get2D();
    return (Float)nLights * EstimateDirect(it, uScattering, *light, uLight,
                                           scene, sampler, arena, handleMedia);
}
Пример #7
0
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;
}
Пример #8
0
COREDLL Spectrum UniformSampleOneLight(const Scene *scene,
		const Point &p, const Normal &n,
		const Vector &wo, BSDF *bsdf, const Sample *sample,
		int lightSampleOffset, int lightNumOffset,
		int bsdfSampleOffset, int bsdfComponentOffset) {
	// Randomly choose a single light to sample, _light_
	int nLights = int(scene->lights.size());
	int lightNum;
	if (lightNumOffset != -1)
		lightNum = Floor2Int(sample->oneD[lightNumOffset][0] *
							 nLights);
	else
		lightNum = Floor2Int(RandomFloat() * nLights);
	lightNum = min(lightNum, nLights-1);
	Light *light = scene->lights[lightNum];
	return (float)nLights *
		EstimateDirect(scene, light, p, n, wo, bsdf, sample,
			lightSampleOffset, bsdfSampleOffset,
			bsdfComponentOffset, 0);
}
Пример #9
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;
}
Пример #10
0
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;
}