def sample_f(self, shading_point): w = shading_point.normal # jitter the up vector v = Vector(0.0024, 1.0, 0.0081).cross(w) v = v.normalize() u = v.cross(w) sample_point = self.sampler.sample_hemisphere() wi = sample_point.x * u + sample_point.y * v + sample_point.z * w wi = wi.normalize() pdf = shading_point.normal * wi / math.pi color = self.surface.get_color(shading_point) return pdf, wi, (self.kd * color / math.pi)
class AreaLight(Light): def __init__(self, shape, cast_shadow): self.shape = shape self.cast_shadow = cast_shadow self.sample = Vector(0.0, 0.0, 0.0) self.light_normal = Vector(0.0, 0.0, 0.0) self.wi = Vector(0.0, 0.0, 0.0) def get_direction(self, shading_point): self.sample = self.shape.sample() self.light_normal = self.shape.normal self.wi = self.sample - shading_point.hit_point self.wi = self.wi.normalize() return -1.0 * self.wi def in_shadow(self, ray, shading_point): ts = (self.sample - ray.origin) * ray.direction for shape in shading_point.scene.shapes: if shape.shadow_hit(ray) and shape.shadow_t < ts: return True return False def L(self): ndotd = -1.0 * self.wi * self.light_normal if ndotd > 0.0: return self.shape.material.Le() else: return Color(0.0, 0.0, 0.0) def G(self, shading_point): ndotd = -1.0 * self.light_normal * self.wi d2 = self.sample.distance(shading_point.hit_point) d2 = d2 * d2 return ndotd / d2 def pdf(self, shading_point): return self.shape.pdf()