def __init__(self, look_from: Vec3 = Vec3(3.0, 3.0, 2.0), look_at: Vec3 = Vec3(0.0, 0.0, -1.0), vec_up: Vec3 = Vec3(0.0, 1.0, 0.0), v_fov: float = 90.0, aspect: float = 1.0, aperture: float = 0.0, focus_dist: float = 1.0): self.lens_radius = aperture / 2.0 theta = v_fov * 3.14159 / 180.0 half_height = math.tan(theta / 2.0) half_width = aspect * half_height w = unit_vector(look_from - look_at) self.u = unit_vector(vec_up.cross(w)) self.v = w.cross(self.u) self.origin = look_from self.upper_left_corner = look_from - \ half_width*self.u*focus_dist + \ half_height*self.v*focus_dist - w*focus_dist self.horizontal = 2 * half_width * self.u * focus_dist self.vertical = -2 * half_height * self.v * focus_dist
def color(ray): t = hit_sphere(Vec3(0.0, 0.0, -1.0), 0.5, ray) if t > 0: N = unit_vector(ray.point_at_parameter(t) - Vec3(0.0, 0.0, -1.0)) return Vec3(N.x + 1.0, N.y + 1.0, N.z + 1.0) * 0.5 unit_direction = unit_vector(ray.direction) t = 0.5 * (unit_direction.y + 1.0) return (1 - t) * Vec3(1.0, 1.0, 1.0) + t * Vec3(0.5, 0.7, 1.0)
def scatter(self, r_in: Ray, hit_rec): if r_in.direction.dot(hit_rec.normal) > 0: outward_normal = -hit_rec.normal n1_n2 = self.ref_idx cosine = self.ref_idx * r_in.direction.dot( hit_rec.normal) / r_in.direction.norm() else: outward_normal = hit_rec.normal n1_n2 = self.inv_ref_idx cosine = -r_in.direction.dot( hit_rec.normal) / r_in.direction.norm() ret_val, refracted = refract(r_in.direction, outward_normal, n1_n2) if ret_val: reflect_prob = schlick(cosine, self.ref_idx) else: reflect_prob = 1.0 if random.random() < reflect_prob: reflected = reflect(unit_vector(r_in.direction), hit_rec.normal) scattered_ray = Ray(hit_rec.p, reflected) else: scattered_ray = Ray(hit_rec.p, refracted) return True, scattered_ray, self.attenuation
def give_fade_blue_down(ray): # goal color is vec3(.5, .7, 1.0) //blue # start is white(1,1,1) # r's original y val goes from -1, 1 # 1 then *.5, to go 0-1 unit_direction = vec3.unit_vector( ray.direction() ) percent = 0.5*(1.0 + unit_direction.e[1]) return vec3.lerp( vec3.vec3(in_list=[1.0, 1.0, 1.0]), vec3.vec3(in_list=[0.5, 0.7, 1.0]), percent)
def scatter(self, r_in: Ray, hit_rec): reflected = reflect( unit_vector(r_in.direction), hit_rec.normal) scattered_ray = Ray(hit_rec.p, reflected + self.fuzz*random_in_unit_sphere()) attenuation = self.albedo return (scattered_ray.direction.dot(hit_rec.normal) > 0), \ scattered_ray, \ attenuation
def test_ray(): ray = Ray(Vec3(0.0,0.0,0.0), Vec3(1.0,1.0,1.0)) print("Origin at %s"%ray.origin) print("Direction is %s"%ray.direction) print("Unit vector direciton is %s"%unit_vector(ray.direction)) distance = -5.0 print("%f meters gives point %s"%(distance, ray.point_at_parameter(distance)))
def refract(v_in: Vec3, normal: Vec3, n1_n2: float) -> [bool, Vec3]: uv_in = unit_vector(v_in) dt = uv_in.dot(normal) discriminant = 1.0 - n1_n2 * n1_n2 * (1 - dt * dt) if discriminant > 0: refracted = n1_n2 * (uv_in - normal * dt) - normal * (discriminant** 0.5) return True, refracted else: return False, None
def color(ray: Ray, world: Object3DList): h_rec = HitRecord() if world.hit(ray, 0.0, float("inf"), h_rec): return Vec3(h_rec.normal.x+1.0, h_rec.normal.y+1.0, h_rec.normal.z+1.0)*0.5 unit_direction = unit_vector(ray.direction) t = 0.5*(unit_direction.y+1.0) return (1-t)*Vec3(1.0,1.0,1.0) + t*Vec3(0.5,0.7,1.0)
def color(ray: Ray, world: Object3DList, depth: int): h_rec = HitRecord() if world.hit(ray, 0.001, float("inf"), h_rec): retval, s_ray, attenuation = h_rec.material.scatter(ray, h_rec) if depth < 50 and retval: return attenuation * color(s_ray, world, depth + 1) else: return Vec3(0.0, 0.0, 0.0) else: unit_direction = unit_vector(ray.direction) t = 0.5 * (unit_direction.y + 1.0) return (1 - t) * Vec3(1.0, 1.0, 1.0) + t * Vec3(0.5, 0.7, 1.0)
def ray_color(r, start_color=None, end_color=None): # This implements the linear interpolation discussed in the notes. # change the start and end vectors for different gradients if not isinstance(r, Ray): raise TypeError("Expected 'Ray' object, got {}".format(type(r))) start_color = start_color if start_color is not None else Vec3(1, 1, 1) # White end_color = end_color if end_color is not None else Vec3(0.5, 0.7, 1.) # Blue unit_direction = unit_vector(r.direction) # scale [-1, 1] to [0, 1] t = 0.5 * (unit_direction.y + 1.0) # do the linear interpolation from start to end color return (1. - t) * start_color + t * end_color