Ejemplo n.º 1
0
def UniformSampleOneLight(scene: Scene, renderer: Renderer, p: Point3d, n: Normal, wo: Vector3d,
                          time: float, bsdf: BSDF, sample: Sample,
                          lightSampleOffsets: [LightSampleOffsets]=None, bsdfSampleOffsets: [BSDFSampleOffsets]=None,
                          lightNumOffset: int=-1) -> Spectrum:
    L = Spectrum(0.0)

    nLights = int(len(scene.lights))
    if nLights == 0:
        return Spectrum(0.0)

    if lightNumOffset != -1:
        lightNum = int((sample.values_array_1d[lightNumOffset][0] * nLights))  # todo floor to int
    else:
        lightNum = int((random() * nLights))  # todo floor to int
    lightNum = min(lightNum, nLights - 1)

    light = scene.lights[lightNum]

    # Initialize light and bsdf samples for single light sample
    if lightSampleOffsets is not None and bsdfSampleOffsets is not None:
        lightSample = LightSample.create_from_sample(sample, lightSampleOffsets, 0)
        bsdfSample = BSDFSample.create_from_sample(sample, bsdfSampleOffsets, 0)
    else:
        lightSample = LightSample.create_from_random()
        bsdfSample = BSDFSample.create_from_random()
    Ld = EstimateDirect(scene, renderer, light, p, n, wo, time, bsdf, lightSample, bsdfSample,
                        BxDFType.BSDF_ALL & ~BxDFType.BSDF_SPECULAR)
    return Ld * float(nLights)
Ejemplo n.º 2
0
def UniformSampleAllLights(scene: Scene, renderer: Renderer, p: Point3d, n: Normal, wo: Vector3d,
                           time: float, bsdf: BSDF, sample: Sample,
                           lightSampleOffsets: [LightSampleOffsets],
                           bsdfSampleOffsets: [BSDFSampleOffsets]) -> Spectrum:
    L = Spectrum(0.0)
    for i in range(len(scene.lights)):
        light = scene.lights[i]
        if lightSampleOffsets is None:
            nSamples = 1
        else:
            nSamples = lightSampleOffsets[i].nSamples

        # Estimate direct lighting from _light_ samples
        Ld = Spectrum(0.0)

        for j in range(nSamples):
            # Find light and BSDF sample values for direct lighting estimate
            if lightSampleOffsets is not None and bsdfSampleOffsets is not None:
                lightSample = LightSample.create_from_sample(sample, lightSampleOffsets[i], j)
                bsdfSample = BSDFSample.create_from_sample(sample, bsdfSampleOffsets[i], j)
            else:
                lightSample = LightSample.create_from_random()
                bsdfSample = BSDFSample.create_from_random()
            Ld += EstimateDirect(scene, renderer, light, p, n, wo, time, bsdf, lightSample, bsdfSample,
                                 BxDFType.BSDF_ALL & ~BxDFType.BSDF_SPECULAR)
        L += Ld / nSamples
    return L
Ejemplo n.º 3
0
    def Li(self, scene, renderer: Renderer, r: Ray, intersection: Intersection, sample: Sample) -> Spectrum:
        # Declare common path integration variables
        pathThroughput = Spectrum(1.0)
        L = Spectrum(0.0)
        ray = deepcopy(r)
        specularBounce = False
        localIsect = Intersection()
        isectp = intersection
        bounces = 0
        while True:
            # Possibly add emitted light at path vertex
            if bounces == 0 or specularBounce:
                L += pathThroughput * isectp.Le(-ray.direction)

            # Sample illumination from lights to find path contribution
            bsdf = isectp.get_bsdf(ray)
            p = bsdf.dgShading.point
            n = bsdf.dgShading.normal
            wo = -ray.direction
            if bounces < self.maxDepth:
                L += pathThroughput * UniformSampleOneLight(scene, renderer, p, n, wo, ray.time, bsdf, sample,
                                                            self.lightSampleOffsets[bounces],
                                                            self.bsdfSampleOffsets[bounces],
                                                            self.lightNumOffset[bounces])
            else:
                L += pathThroughput * UniformSampleOneLight(scene, renderer, p, n, wo, ray.time, bsdf, sample)

            # Sample BSDF to get new path direction

            # Get _outgoingBSDFSample_ for sampling new path direction
            if bounces < self.maxDepth:
                outgoingBSDFSample = BSDFSample.create_from_sample(sample, self.pathSampleOffsets[bounces], 0)
            else:
                outgoingBSDFSample = BSDFSample.create_from_random()

            wi, pdf, flags, f = bsdf.Sample_f(wo, outgoingBSDFSample, BxDFType.BSDF_ALL)
            if f.get_is_black() or pdf == 0.0:
                break

            specularBounce = (flags & BxDFType.BSDF_SPECULAR) != 0
            pathThroughput *= f * math.fabs(Vector3d.dot(wi, n)) / pdf
            ray = Ray(p, wi, 0.01, ray.max_t)

            # Possibly terminate the path
            if bounces > 3:
                continueProbability = min(0.5, pathThroughput.y())
                if random() > continueProbability:
                    break
                pathThroughput /= continueProbability

            if bounces == self.maxDepth:
                break

            # Find next vertex of path
            if not scene.get_intersection(ray, localIsect):
                if specularBounce:
                    for i in range(scene.lights.size()):
                        L += pathThroughput * scene.lights[i].get_Le(ray)
                break
            # pathThroughput *= renderer->Transmittance(scene, ray, NULL, rng, arena);
            isectp = localIsect

            bounces += 1

        return L