Exemple #1
0
def ray_color(r: RayList, world: HittableList, depth: int) \
        -> Tuple[Optional[RayList], Optional[Vec3List], Vec3List]:
    length = len(r)
    if not r.direction().e.any():
        return None, None, Vec3List.new_zero(length)

    # Calculate object hits
    rec_list: HitRecordList = world.hit(r, 0.001, cp.inf)

    # Useful empty arrays
    empty_vec3list = Vec3List.new_zero(length)
    empty_array_float = cp.zeros(length, cp.float32)
    empty_array_bool = cp.zeros(length, cp.bool)
    empty_array_int = cp.zeros(length, cp.int32)

    # Background / Sky
    unit_direction = r.direction().unit_vector()
    sky_condition = Vec3List.from_array((unit_direction.length() > 0)
                                        & (rec_list.material == 0))
    t = (unit_direction.y() + 1) * 0.5
    blue_bg = (Vec3List.from_vec3(Color(1, 1, 1), length).mul_ndarray(1 - t) +
               Vec3List.from_vec3(Color(0.5, 0.7, 1), length).mul_ndarray(t))
    result_bg = Vec3List(cp.where(sky_condition.e, blue_bg.e,
                                  empty_vec3list.e))
    if depth <= 1:
        return None, None, result_bg

    # Material scatter calculations
    materials: Dict[int, Material] = world.get_materials()
    scattered_list = RayList.new_zero(length)
    attenuation_list = Vec3List.new_zero(length)
    for mat_idx in materials:
        mat_condition = (rec_list.material == mat_idx)
        mat_condition_3 = Vec3List.from_array(mat_condition)
        if not mat_condition.any():
            continue

        ray = RayList(
            Vec3List(cp.where(mat_condition_3.e, r.orig.e, empty_vec3list.e)),
            Vec3List(cp.where(mat_condition_3.e, r.dir.e, empty_vec3list.e)))
        rec = HitRecordList(
            Vec3List(
                cp.where(mat_condition_3.e, rec_list.p.e, empty_vec3list.e)),
            cp.where(mat_condition, rec_list.t, empty_array_float),
            cp.where(mat_condition, rec_list.material, empty_array_int),
            Vec3List(
                cp.where(mat_condition_3.e, rec_list.normal.e,
                         empty_vec3list.e)),
            cp.where(mat_condition, rec_list.front_face, empty_array_bool))
        ray, rec, idx_list = compress(ray, rec)

        scattered, attenuation = materials[mat_idx].scatter(ray, rec)
        scattered, attenuation = decompress(scattered, attenuation, idx_list,
                                            length)
        scattered_list += scattered
        attenuation_list += attenuation

    return scattered_list, attenuation_list, result_bg
def ray_color(r, world, depth):
    length = len(r)
    if not r.direction().e.any():
        return None, None, Vec3List.new_zero(length)

    rec_list = world.hit(r, 0.001, cp.inf)

    empty_vec3list = Vec3List.new_zero(length)
    empty_array_float = cp.zeros(length, cp.float32)
    empty_array_bool = cp.zeros(length, cp.bool)
    empty_array_int = cp.zeros(length, cp.int32)

    unit_direction = r.direction().unit_vector()
    sky_condition = Vec3List.from_array((unit_direction.length() > 0)
                                        & (rec_list.material == 0))
    t = (unit_direction.y() + 1) * 0.5
    blue_bg = (Vec3List.from_vec3(Color(1, 1, 1), length).mul_ndarray(1 - t) +
               Vec3List.from_vec3(Color(0.5, 0.7, 1), length).mul_ndarray(t))
    result_bg = Vec3List(cp.where(sky_condition.e, blue_bg.e,
                                  empty_vec3list.e))
    if depth <= 1:
        return None, None, result_bg

    materials = world.get_materials()
    scattered_list = RayList.new_zero(length)
    attenuation_list = Vec3List.new_zero(length)
    for mat_idx in materials:
        mat_condition = (rec_list.material == mat_idx)
        mat_condition_3 = Vec3List.from_array(mat_condition)
        if not mat_condition.any():
            continue

        ray = RayList(
            Vec3List(
                cp.where(mat_condition_3.e,
                         r.origin().e, empty_vec3list.e)),
            Vec3List(
                cp.where(mat_condition_3.e,
                         r.direction().e, empty_vec3list.e)))
        rec = HitRecordList(
            Vec3List(
                cp.where(mat_condition_3.e, rec_list.p.e, empty_vec3list.e)),
            cp.where(mat_condition, rec_list.t, empty_array_float),
            cp.where(mat_condition, rec_list.material, empty_array_int),
            Vec3List(
                cp.where(mat_condition_3.e, rec_list.normal.e,
                         empty_vec3list.e)),
            cp.where(mat_condition, rec_list.front_face, empty_array_bool))
        ray, rec, idx_list = compress(ray, rec)

        scattered, attenuation = materials[mat_idx].scatter(ray, rec)
        scattered, attenuation = decompress(scattered, attenuation, idx_list,
                                            length)
        scattered_list += scattered
        attenuation_list += attenuation

    return scattered_list, attenuation_list, result_bg
Exemple #3
0
 def __init__(self, point: Vec3List, t: cp.ndarray, mat: cp.ndarray,
              normal: Vec3List = Vec3List.new_zero(0),
              front_face: cp.ndarray = cp.array([])) -> None:
     self.p = point
     self.t = t
     self.material = mat
     self.normal = normal
     self.front_face = front_face
 def __init__(self,
              point,
              t,
              mat,
              normal=Vec3List.new_zero(0),
              front_face=cp.array([])):
     self.p = point
     self.t = t
     self.material = mat
     self.normal = normal
     self.front_face = front_face
def decompress(r, a, idx, length):
    if idx is None:
        return r, a

    old_idx = cp.arange(len(idx))
    new_r = RayList.new_zero(length)
    new_r.origin().e[idx] = r.origin().e[old_idx]
    new_r.direction().e[idx] = r.direction().e[old_idx]

    new_a = Vec3List.new_zero(length)
    new_a.e[idx] = a.e[old_idx]

    return new_r, new_a
Exemple #6
0
def decompress(r: RayList, a: Vec3List, idx: Optional[np.ndarray],
               length: int) -> Tuple[RayList, Vec3List]:
    if idx is None:
        return r, a

    old_idx = np.arange(len(idx))

    new_r = RayList.new_zero(length)
    new_r.orig.e[idx] = r.orig.e[old_idx]
    new_r.dir.e[idx] = r.dir.e[old_idx]

    new_a = Vec3List.new_zero(length)
    new_a.e[idx] = a.e[old_idx]

    return new_r, new_a
 def new_zero(length):
     return RayList(Vec3List.new_zero(length), Vec3List.new_zero(length))
Exemple #8
0
 def new_zero(length: int) -> RayList:
     return RayList(Vec3List.new_zero(length), Vec3List.new_zero(length))
Exemple #9
0
def ray_color(r: RayList, world: HittableList, depth: int) -> Vec3List:
    length = len(r)
    if not r.direction().e.any():
        return Vec3List.new_zero(length)

    # Calculate object hits
    rec_list: HitRecordList = world.hit(r, 0.001, np.inf)

    # Useful empty arrays
    empty_vec3list = Vec3List.new_zero(length)
    empty_array_float = np.zeros(length, np.float32)
    empty_array_bool = np.zeros(length, np.bool)
    empty_array_int = np.zeros(length, np.int32)

    # Background / Sky
    unit_direction = r.direction().unit_vector()
    sky_condition = Vec3List.from_array((unit_direction.length() > 0)
                                        & (rec_list.material == 0))
    t = (unit_direction.y() + 1) * 0.5
    blue_bg = (Vec3List.from_vec3(Color(1, 1, 1), length).mul_ndarray(1 - t) +
               Vec3List.from_vec3(Color(0.5, 0.7, 1), length).mul_ndarray(t))
    result_bg = Vec3List(np.where(sky_condition.e, blue_bg.e,
                                  empty_vec3list.e))
    if depth <= 1:
        return result_bg

    # Per-material preparations
    materials: Dict[int, Material] = world.get_materials()
    material_dict: Dict[int, Tuple[RayList, HitRecordList]] = dict()
    for mat_idx in materials:
        mat_condition = (rec_list.material == mat_idx)
        mat_condition_3 = Vec3List.from_array(mat_condition)
        if not mat_condition.any():
            continue
        raylist_temp = RayList(
            Vec3List(np.where(mat_condition_3.e, r.orig.e, empty_vec3list.e)),
            Vec3List(np.where(mat_condition_3.e, r.dir.e, empty_vec3list.e)))
        reclist_temp = HitRecordList(
            Vec3List(
                np.where(mat_condition_3.e, rec_list.p.e, empty_vec3list.e)),
            np.where(mat_condition, rec_list.t, empty_array_float),
            np.where(mat_condition, rec_list.material, empty_array_int),
            Vec3List(
                np.where(mat_condition_3.e, rec_list.normal.e,
                         empty_vec3list.e)),
            np.where(mat_condition, rec_list.front_face, empty_array_bool))
        material_dict[mat_idx] = raylist_temp, reclist_temp

    # Material scatter calculations
    scattered_list = RayList.new_zero(length)
    attenuation_list = Vec3List.new_zero(length)
    for key in material_dict:
        ray, rec = material_dict[key]
        ray, rec, idx_list = compress(ray, rec)

        scattered, attenuation = materials[key].scatter(ray, rec)
        scattered, attenuation = decompress(scattered, attenuation, idx_list,
                                            length)
        scattered_list += scattered
        attenuation_list += attenuation
    result_hittable = (attenuation_list *
                       ray_color(scattered_list, world, depth - 1))

    return result_hittable + result_bg