def scatter(self, this_ray, rec, attenuation, scattered): outward_normal = v.vec3(0.0, 0.0, 0.0) refracted = v.vec3(0.0, 0.0, 0.0) reflected = reflect(this_ray.direction.unit_vector(), rec.normal) ni_over_nt = 0.0 reflect_prob = 0.0 cosine = 0.0 attenuation = v.vec3(1.0, 1.0, 1.0) if this_ray.direction.dot_product(rec.normal) > 0: outward_normal = -rec.normal ni_over_nt = self.ri cosine = self.ri * this_ray.direction.dot_product(rec.normal) / abs(this_ray.direction) else: outward_normal = rec.normal ni_over_nt = 1.0 / self.ri cosine = -this_ray.direction.dot_product(rec.normal) / abs(this_ray.direction) refract_result = refract(this_ray.direction, outward_normal, ni_over_nt, refracted) if refract_result[0]: reflect_prob = schlick(cosine, self.ri) else: scattered = r.ray(rec.p, reflected) reflect_prob = 1.0 if random.random() < reflect_prob: scattered = r.ray(rec.p, reflected) else: scattered = r.ray(rec.p, refract_result[1]) return True, scattered, attenuation
def get_ray(self, u_coord, v_coord): ''' Return ray at position. ''' rd = self.lens_radius * random_in_unit_disk() offset = self.cu * rd.x + self.cv * rd.y return r.ray( self.origin + offset, self.lower_left_corner + u_coord * self.horizontal + v_coord * self.vertical - self.origin - offset)
def colour(this_ray, world, depth): ''' Colour pixel based on ray hit. ''' rec = hit_record() if world.hit(this_ray, 0.001, MAXFLOAT, rec): scattered = r.ray(v.vec3(0.0, 0.0, 0.0), v.vec3(0.0, 0.0, 0.0)) attenuation = v.vec3(0.0, 0.0, 0.0) hit = rec.material.scatter(this_ray, rec, attenuation, scattered) if depth < 50 and hit[0]: # hit 1 = scattered, hit 2 = albedo return colour(hit[1], world, depth + 1) * hit[2] # return coloured ray else: return v.vec3(0.0, 0.0, 0.0) # blue background unit_direction = v.vec3.unit_vector(this_ray.direction) t = 0.5 * (unit_direction.y + 1.0) return (1.0 - t) * v.vec3(1.0, 1.0, 1.0) + t * v.vec3(0.5, 0.7, 1.0)
def scatter(self, this_ray, rec, attenuation, scattered): reflected = reflect(this_ray.direction.unit_vector(), rec.normal) offset = reflected * 0.01 scattered = r.ray(rec.p, reflected + offset + self.fuzz * random_in_unit_sphere()) dot = scattered.direction.dot_product(rec.normal) return dot > 0, scattered, self.albedo
def scatter(self, this_ray, rec, attenuation, scattered): target = rec.p + rec.normal + random_in_unit_sphere() scattered = r.ray(rec.p, target-rec.p) return True, scattered, self.albedo