def generate_ray_differential(self, sample: 'CameraSample') -> [FLOAT, 'geo.RayDifferential']: """ Generate ray differential. """ p_ras = geo.Point(sample.imageX, sample.imageY, 0.) p_cam = self.r2c(p_ras) ray = geo.RayDifferential(geo.Point(0., 0., 0.), geo.Vector.from_arr(geo.normalize(p_cam)), 0., np.inf) # ray.d is a geo.Vector init from a geo.Point from pytracer.montecarlo import concentric_sample_disk if self.lens_rad > 0.: # depth of field lens_u, lens_v = \ concentric_sample_disk(sample.lens_u, sample.lens_v) lens_u *= self.lens_rad lens_v *= self.lens_rad # compute point on focal plane ft = self.focal_dist / ray.d.z Pfoc = ray(ft) # update ray ray.o = geo.Point(lens_u, lens_v, 0.) ray.d = geo.normalize(Pfoc - ray.o) if self.lens_rad > 0.: # with defocus blue lens_u, lens_v = concentric_sample_disk(sample.lens_u, sample.lens_v) lens_u *= self.lens_rad lens_v *= self.lens_rad # compute point on focal plane dx = geo.normalize(self.dxCam + p_cam) ft = self.focal_dist / dx.z Pfoc = geo.Point(0., 0., 0.) + ft * dx ray.rxOrigin = geo.Point(lens_u, lens_v, 0.) ray.rxDirection = geo.normalize(Pfoc - ray.rxOrigin) dy = geo.normalize(geo.Vector.from_arr(p_cam + self.dyCam)) ft = self.focal_dist / dy.z Pfoc = geo.Point(0., 0., 0.) + ft * dy ray.ryOrigin = geo.Point(lens_u, lens_v, 0.) ray.ryDirection = geo.normalize(Pfoc - ray.ryOrigin) else: ray.rxOrigin = ray.ryOrigin = ray.o ray.rxDirection = geo.normalize(self.dxCam + p_cam) # geo.Vector + geo.Point => geo.Vector ray.ryDirection = geo.normalize(self.dyCam + p_cam) ray.time = sample.time ray = self.c2w(ray) ray.has_differentials = True return [1., ray]
def test_ray_differential_from_ray_differential(self, vec, pnt): r0 = geo.RayDifferential(pnt, vec) r1 = geo.RayDifferential.from_rd(r0) assert r1.time == r0.time assert r1.depth == r0.depth assert r1.has_differentials == r0.has_differentials assert not id(r1.o) == id(r0.o) assert not id(r1.d) == id(r0.d) assert not id(r1.rxDirection) == id(r0.rxDirection) assert not id(r1.ryDirection) == id(r0.ryDirection) assert not id(r1.rxOrigin) == id(r0.rxOrigin) assert not id(r1.ryOrigin) == id(r0.ryOrigin)
def test_ray_differential_scale(self, vec, pnt): ray = geo.RayDifferential(pnt, vec) ray.rxOrigin = ray.ryOrigin = pnt ray.rxDirection = vec + geo.Vector(rng(), rng(), rng()) ray.ryDirection = vec + geo.Vector(rng(), rng(), rng()) s = rng() r = geo.RayDifferential.from_rd(ray) ray.scale_differential(s) assert ray.rxOrigin == r.o + (r.rxOrigin - r.o) * s assert ray.ryOrigin == r.o + (r.ryOrigin - r.o) * s assert ray.rxDirection == r.d + (r.rxDirection - r.d) * s assert ray.ryDirection == r.d + (r.ryDirection - r.d) * s assert isinstance(ray.rxOrigin, geo.Point) assert isinstance(ray.ryOrigin, geo.Point) assert isinstance(ray.rxDirection, geo.Vector) assert isinstance(ray.ryDirection, geo.Vector)
def estimate_direct(scene: 'Scene', renderer: 'Renderer', light: 'Light', p: 'geo.Point', n: 'geo.Normal', wo: 'geo.Vector', r_eps: FLOAT, time: FLOAT, bsdf: 'BSDF', light_smp: 'LightSample', bsdf_smp: 'BSDFSample', flags: 'BDFType', rng=np.random.rand) -> 'Spectrum': """ estimate_direct() Estimate direct lighting using MC Multiple Importance Sampling. """ from pytracer.reflection import BDFType Ld = Spectrum(0.) # sample light source Li, wi, light_pdf, vis = light.sample_l(p, r_eps, light_smp, time) if light_pdf > 0. and not Li.is_black(): f = bsdf.f(wo, wi, flags) if not f.is_black() and vis.unoccluded(scene): # add contribution to reflected radiance ## account for attenuation due to participating media, ## left for `VolumeIntegrator` to do Li *= vis.transmittance(scene, renderer, None, rng) if light.is_delta_light(): Ld += f * Li * (wi.abs_dot(n) / light_pdf) else: from pytracer.montecarlo import power_heuristic bsdf_pdf = bsdf.pdf(wo, wi, flags) weight = power_heuristic( 1, light_pdf, 1, bsdf_pdf) # Power heuristic for HG phase function Ld += f * Li * (wi.abs_dot(n) * weight / light_pdf) # sample BSDF ## no need if delta light if not light.is_delta_light(): bsdf_pdf, wi, smp_type, f = bsdf.sample_f(wo, bsdf_smp, flags) if not f.is_black() and bsdf_pdf > 0.: wt = 1. if not (smp_type & BDFType.SPECULAR ).v == 0: # MIS not apply to specular direction light_pdf = light.pdf(p, wi) if light_pdf == 0.: return Ld from pytracer.montecarlo import power_heuristic wt = power_heuristic(1, bsdf_pdf, 1, light_pdf) # add contribution Li = Spectrum(0.) ray = geo.RayDifferential(p, wi, r_eps, np.inf, time) hit, light_isect = scene.intersect(ray) if hit: if light_isect.primitive.get_area_light() == light: Li = light_isect.le(-wi) else: Li = light.le(ray) # light illum. if not Li.is_black(): Li *= renderer.transmittance(scene, ray, None, rng) # attenuation Ld += f * Li * wi.abs_dot(n) * wt / bsdf_pdf return Ld
def test_ray_differential_call(self, vec, pnt): ray = geo.RayDifferential(pnt, vec) t = rng() p = ray(t) assert isinstance(pnt, geo.Point) assert p == pnt + vec * t
def test_ray_differential_from_parent(self, vec, pnt): r0 = geo.RayDifferential(pnt, vec) r1 = geo.RayDifferential.from_parent(pnt, vec, r0) assert r1.time == r0.time assert r1.depth == r0.depth + 1