def __init__(self, aspect, vfov, aperture, focus_dist, lookfrom, lookat, vup=Vec(0, 1, 0)): self.lens_radius = aperture / 2 theta = vfov * pi / 180 half_height = tan(theta / 2) half_width = aspect * half_height self.origin = lookfrom w = Vec.unit_vector(lookfrom - lookat) u = Vec.unit_vector(Vec.cross(vup, w)) v = Vec.cross(w, u) self.lower_left = self.origin - half_width * focus_dist * u - half_height * focus_dist * v - focus_dist * w self.horizontal = 2 * half_width * focus_dist * u self.vertical = 2 * half_height * focus_dist * v self.u = u self.v = v
def scatter(self, r_in, hit_rec, attenuation, r_scattered): reflected = Vec.reflect_mv(Vec.unit_vector(r_in.direction), hit_rec.n) r_scattered.A = hit_rec.p r_scattered.B = Sphere.random_in_unit_sphere().mul( self.fuzz).add(reflected) attenuation.x = self.albedo.x attenuation.y = self.albedo.y attenuation.z = self.albedo.z return Vec.dot(r_scattered.direction, hit_rec.n) > 0
def refract(v, n, ior, refracted): uv = Vec.unit_vector(v) dt = Vec.dot(uv, n) disc = 1 - ior * ior * (1 - dt * dt) if disc > 0: sqrt_disc = sqrt(disc) refracted.x = ior * (uv.x - n.x * dt) - n.x * sqrt_disc refracted.y = ior * (uv.y - n.y * dt) - n.y * sqrt_disc refracted.z = ior * (uv.z - n.z * dt) - n.z * sqrt_disc return True else: return False
def color(ray, world, depth): hit_rec = HitRecord() if world.hit(ray, 0.001, float('inf'), hit_rec): scattered = Ray() attenuation = Vec() hit_mat = hit_rec.mat if depth < MAXIMUM_DEPTH and hit_mat.scatter(ray, hit_rec, attenuation, scattered): return color(scattered, world, depth + 1).vec_mul(attenuation) else: return Vec() else: unit_dir = Vec.unit_vector(ray.direction) t = 0.5 * (unit_dir.y + 1) ti = 1 - t return Vec(ti * BG_COL_A.x + t * BG_COL_B.x, ti * BG_COL_A.y + t * BG_COL_B.y, ti * BG_COL_A.z + t * BG_COL_B.z)