def scan_frame(world: HittableList, cam: Camera, image_width: int, image_height: int, max_depth: int) -> Vec3List: length = image_width * image_height i_list = cp.tile(cp.arange(image_width), image_height) j_list = cp.concatenate( cp.transpose(cp.tile(cp.arange(image_height), (image_width, 1)))) u: cp.ndarray = (random_float_list(length) + i_list) / (image_width - 1) v: cp.ndarray = (random_float_list(length) + j_list) / (image_height - 1) r: RayList = cam.get_ray(u, v) return ray_color_loop(r, world, max_depth)
def random_in_unit_sphere_list(size: int) -> Vec3List: u = random_float_list(size) v = random_float_list(size) theta = u * 2 * cp.pi phi = cp.arccos(2 * v - 1) r = cp.cbrt(random_float_list(size)) sinTheta = cp.sin(theta) cosTheta = cp.cos(theta) sinPhi = cp.sin(phi) cosPhi = cp.cos(phi) x = r * sinPhi * cosTheta y = r * sinPhi * sinTheta z = r * cosPhi return Vec3List(cp.transpose(cp.array([x, y, z])))
def scatter(self, r_in: RayList, rec: HitRecordList) \ -> Tuple[RayList, Vec3List]: etai_over_etat = cp.where( rec.front_face, 1 / self.ref_idx, self.ref_idx ) unit_direction = r_in.direction().unit_vector() cos_theta = -unit_direction @ rec.normal cos_theta = cp.where(cos_theta > 1, 1, cos_theta) sin_theta = cp.sqrt(1 - cos_theta**2) reflect_prob = self.schlick(cos_theta, etai_over_etat) reflect_condition = ( (etai_over_etat * sin_theta > 1) | (random_float_list(len(r_in)) < reflect_prob) ) # total internal reflection reflected = (unit_direction.mul_ndarray(reflect_condition)).reflect( rec.normal.mul_ndarray(reflect_condition) ) # refraction refracted = (unit_direction.mul_ndarray(~reflect_condition)).refract( rec.normal.mul_ndarray(~reflect_condition), etai_over_etat ) direction = reflected + refracted condition = rec.t > 0 scattered = RayList( rec.p.mul_ndarray(condition), direction.mul_ndarray(condition) ) attenuation = Vec3List.from_array(condition) * Color(1, 1, 1) return scattered, attenuation
def scan_line(j: int, world: HittableList, cam: Camera, image_width: int, image_height: int, samples_per_pixel: int, max_depth: int) -> Img: img = Img(image_width, 1) row_pixel_color = Vec3List.from_vec3(Color(), image_width) for s in range(samples_per_pixel): u: np.ndarray = (random_float_list(image_width) + np.arange(image_width)) / (image_width - 1) v: np.ndarray = (random_float_list(image_width) + j) / (image_height - 1) r: RayList = cam.get_ray(u, v) row_pixel_color += ray_color(r, world, max_depth) img.write_pixel_list(0, row_pixel_color, samples_per_pixel) return img
def random(_min: float = 0, _max: float = 1) -> Vec3: return Vec3(*random_float_list(3, _min, _max))
def random_in_unit_disk(size: int) -> cp.ndarray: r = cp.sqrt(random_float_list(size)) theta = random_float_list(size) * 2 * cp.pi return cp.array([r * cp.cos(theta), r * cp.sin(theta)])
def random_unit_vector(size: int) -> Vec3List: a = random_float_list(size, 0, 2 * cp.pi) z = random_float_list(size, -1, 1) r = cp.sqrt(1 - z**2) return Vec3List( cp.transpose(cp.array([r * cp.cos(a), r * cp.sin(a), z])))