示例#1
0
文件: path.py 项目: neodyme60/raypy
    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
示例#2
0
    def run(self):
        """Execute the task."""

        print "executing task %d/%d" % (self.task_num, self.task_count)

        # get sub-sampler for SamplerRendererTask
        sampler = self.main_sampler.get_sub_sampler(self.task_num,
                                                    self.task_count)
        if not sampler:
            return

        # Declare local variables used for rendering loop
        rng = RNG(self.task_num)

        # allocate space for samples and intersections
        max_samples = sampler.maximum_sample_count()
        samples = self.orig_sample.duplicate(max_samples)
        rays = [None] * max_samples
        Ls = [None] * max_samples
        Ts = [None] * max_samples
        isects = []  # Intersection[max_samples]
        for i in range(max_samples):
            isects.append(Intersection())

        # get samples from Sampler and update image
        while True:
            sample_count = sampler.get_more_samples(samples, rng)

            # if no more samples to compute, exit
            if sample_count <= 0:
                break

            # generate camera rays and compute radiance along rays
            for i in range(sample_count):
                # find camera ray for samples[i]
                ray_weight, ray_diff = self.camera.generate_ray_differential(
                    samples[i])

                rays[i] = ray_diff
                coeff = 1.0 / math.sqrt(sampler.samples_per_pixel)
                ray_diff.scale_differentials(coeff)

                # evaluate radiance along camera ray
                if ray_weight > 0.0:
                    radiance, intersection, Ts_i = \
                              self.renderer.Li(self.scene,
                                               ray_diff,
                                               samples[i],
                                               rng,
                                               isects[i])
                    Ls_i = ray_weight * radiance
                else:
                    Ls_i = Spectrum(0.0)
                    Ts_i = Spectrum(1.0)

                Ls[i] = Ls_i
                Ts[i] = Ts_i

                # check for unexpected radiance values
                if Ls_i.has_nan():
                    logger.error(
                        "Not-a-number radiance value returned for image sample.  Setting to black."
                    )
                    Ls_i = Spectrum(0.0)
                elif Ls_i.y() < -1e-5:
                    logger.error(
                        "Negative luminance value, %f, returned for image sample.  Setting to black."
                        % Ls_i.y())
                    Ls_i = Spectrum(0.0)
                elif Ls_i.y() == float('inf'):
                    logger.error(
                        "Infinite luminance value returned for image sample.  Setting to black."
                    )
                    Ls_i = Spectrum(0.0)

            # report sample results to Sampler, add contributions to image
            if sampler.report_results(samples, rays, Ls, isects, sample_count):
                for i in range(sample_count):
                    self.camera.film.add_sample(samples[i], Ls[i])

        # clean up after SamplerRendererTask is done with its image region
        pass
示例#3
0
    def run(self):
        """Execute the task."""

        print "executing task %d/%d" % (self.task_num, self.task_count)
        
        # get sub-sampler for SamplerRendererTask
        sampler = self.main_sampler.get_sub_sampler(self.task_num,
                                                    self.task_count)
        if not sampler:
            return
        
        # Declare local variables used for rendering loop
        rng = RNG(self.task_num)

        # allocate space for samples and intersections
        max_samples = sampler.maximum_sample_count()
        samples = self.orig_sample.duplicate(max_samples)
        rays = [None] * max_samples
        Ls = [None] * max_samples
        Ts = [None] * max_samples
        isects = [] # Intersection[max_samples]
        for i in range(max_samples):
            isects.append(Intersection())

        # get samples from Sampler and update image
        while True:
            sample_count = sampler.get_more_samples(samples, rng)

            # if no more samples to compute, exit
            if sample_count <= 0:
                break
            
            # generate camera rays and compute radiance along rays
            for i in range(sample_count):
                # find camera ray for samples[i]
                ray_weight, ray_diff = self.camera.generate_ray_differential(samples[i])
                
                rays[i] = ray_diff
                coeff = 1.0 / math.sqrt(sampler.samples_per_pixel)
                ray_diff.scale_differentials(coeff)
                
                # evaluate radiance along camera ray
                if ray_weight > 0.0:
                    radiance, intersection, Ts_i = \
                              self.renderer.Li(self.scene,
                                               ray_diff,
                                               samples[i],
                                               rng,
                                               isects[i])
                    Ls_i = ray_weight * radiance
                else:
                    Ls_i = Spectrum(0.0)
                    Ts_i = Spectrum(1.0)

                Ls[i] = Ls_i
                Ts[i] = Ts_i
                
                # check for unexpected radiance values
                if Ls_i.has_nan():
                    logger.error(
                        "Not-a-number radiance value returned for image sample.  Setting to black.")
                    Ls_i = Spectrum(0.0)
                elif Ls_i.y() < -1e-5:
                    logger.error(
                        "Negative luminance value, %f, returned for image sample.  Setting to black." % Ls_i.y())
                    Ls_i = Spectrum(0.0)
                elif Ls_i.y() == float('inf'):
                    logger.error(
                        "Infinite luminance value returned for image sample.  Setting to black.")
                    Ls_i = Spectrum(0.0)

            # report sample results to Sampler, add contributions to image
            if sampler.report_results(samples, rays, Ls, isects, sample_count):
                for i in range(sample_count):
                    self.camera.film.add_sample(samples[i], Ls[i])

        # clean up after SamplerRendererTask is done with its image region
        pass