Exemple #1
0
def main(size, k, steps, output_path):
    # utils.random_seed(2**7)
    utils.random_seed(2**10)
    size = size, size

    camera = Camera(vector(0, 0, -1))
    objects = ObjectList(randomize_objects())

    with Pool(os.cpu_count()) as pool:
        image = pool.imap(
            partial(
                render_row,
                size=size,
                camera=camera,
                objects=objects,
                k=k,
                max_steps=steps,
            ),
            range(size[0]),
        )
        image = list(tqdm(image, total=size[0]))

    image = torch.stack(image, 1)
    image = image.clamp(0, 1)
    image = image.flip(1)
    image = to_pil_image(image)

    os.makedirs(output_path, exist_ok=True)
    image.save(
        os.path.join(output_path, "{}_{}_{}.png".format(size[0], k, steps)))
    plt.imshow(image)
    plt.show()
Exemple #2
0
def color_at(object: Object, position, normal, scene: Scene):
    color = vector()
    color = object.material.ambient * color

    to_cam = scene.camera - position
    specular_k = 50

    for light in scene.lights:
        to_light = Ray(position, light.position - position)
        color += (
            object.material.color
            * object.material.diffuse
            * max(torch.dot(normal, to_light.direction), 0)
        )

        half_vector = normalize(to_light.direction + to_cam)
        color += (
            light.color
            * object.material.specular
            * max(torch.dot(normal, half_vector), 0) ** specular_k
        )

    color = color.clamp(0, 1)

    return color
Exemple #3
0
def ray_trace(ray: Ray, objects: ObjectList, max_steps):
    if max_steps == 0:
        return vector(0, 0, 0)

    intersection = objects.intersects(ray)
    if intersection is None:
        return vector(0.2, 0.2, 0.2)

    position = ray.position_at(intersection.t)
    normal = intersection.object.normal_at(position)

    emitted = intersection.object.material.emit()
    reflection = intersection.object.material.reflect(ray, intersection.t,
                                                      normal)
    if reflection is None:
        return emitted

    return emitted + reflection.attenuation * ray_trace(
        reflection.ray, objects, max_steps - 1)
Exemple #4
0
def randomize_objects():
    floor = Sphere(vector(0, -102, 1), 100,
                   Diffuse(vector(1 / 3, 1 / 3, 1 / 3)))
    objects = [floor]

    for _ in range(8):
        floor_to_center = vector(0, -2, 1) - floor.center
        floor_to_center[0] += random.uniform(-4, 4)
        floor_to_center[2] += random.uniform(0, 8)

        radius = random.uniform(0.25, 1.5)
        center = floor.center + normalize(
            floor_to_center) * floor.radius + radius

        mat = random.choice([Diffuse, Metal])

        object = Sphere(center, radius, mat(vector(0, 0, 0).uniform_(0, 1)))
        objects.append(object)

    objects[8].material = Light(vector(1, 1, 1))

    return objects
Exemple #5
0
def ray_trace(ray: Ray, scene: Scene):
    color = vector()

    ot = None
    for object in scene.objects:
        t = object.intersects(ray)
        if t is None:
            continue
        if ot is None:
            ot = object, t
        if t < ot[1]:
            ot = object, t

    if ot is None:
        return color

    object, t = ot
    del ot

    position = ray.position_at(t)
    normal = object.normal_at(position)
    color += color_at(object, position, normal, scene)

    return color
Exemple #6
0
def main():
    size = 256, 256

    camera = vector(0, 0, -1)
    objects = [
        Sphere(vector(0, 0, 0), 0.5, Metal(vector(1, 0, 0))),
        Sphere(vector(0, -1, 1), 0.5, Metal(vector(0, 1, 0))),
    ]
    lights = [
        Light(vector(1.5, -0.5, -10), vector(1, 1, 1)),
    ]
    scene = Scene(camera=camera, objects=objects, lights=lights)

    view = build_view(size)
    image = torch.zeros(3, *size, dtype=torch.float)

    for i, j in tqdm(product(range(size[0]), range(size[1])), total=size[0] * size[1]):
        ray = Ray(camera, view[:, i, j] - camera)
        image[:, i, j] = ray_trace(ray, scene)

    image = to_pil_image(image)
    image.save("./ray_tracing/output.png")
    plt.imshow(image)
    plt.show()
Exemple #7
0
 def emit(self):
     return vector(0, 0, 0)
Exemple #8
0
    def ray_to_position(self, x, y):
        position = vector(2 * x - 1, 2 * y - 1, 0)

        return Ray(self.origin, position - self.origin)