def test_lighting_with_surface_in_shadow(self, background): eyev = Vector(0, 0, -1) normalv = Vector(0, 0, -1) light = PointLight(Point(0, 0, -10), Color(1, 1, 1)) in_shadow = True result = background['m'].lighting(Sphere(), light, background['position'], eyev, normalv, in_shadow) assert result == Color(0.1, 0.1, 0.1)
def test_shading_intersection_from_inside(self, default_world): w = default_world w.light_source = PointLight(Point(0, 0.25, 0), Color.white()) r = Ray(Point(0, 0, 0), Vector(0, 0, 1)) shape = w.objects[1] i = Intersection(0.5, shape) comps = i.prepare_computations(r) c = w.shade_hit(comps) assert c == Color(0.90498, 0.90498, 0.90498)
def default_world(): w = World() w.light_source = PointLight(Point(-10, 10, -10), Color.white()) s1 = Sphere() s1.material.color = Color(0.8, 1.0, 0.6) s1.material.diffuse = 0.7 s1.material.specular = 0.2 s2 = Sphere() s2.transformation = scaling(0.5, 0.5, 0.5) w.add(s1, s2) return w
def test_constructing_ppm_pixel_data(self): c = Canvas(5, 3) c1 = Color(1.5, 0, 0) c2 = Color(0, 0.5, 0) c3 = Color(-0.5, 0, 1) c.write_pixel(0, 0, c1) c.write_pixel(2, 1, c2) c.write_pixel(4, 2, c3) ppm = c.to_ppm() assert ''.join(ppm[3:]) == "255 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n" \ "0 0 0 0 0 0 0 128 0 0 0 0 0 0 0\n" \ "0 0 0 0 0 0 0 0 0 0 0 0 0 0 255\n"
def test_shade_hit_is_given_an_intersection_in_shadow(self): w = World() w.light_source = PointLight(Point(0, 0, -10), Color.white()) s1 = Sphere() s2 = Sphere() s2.transformation = translation(0, 0, 10) w.add(s1, s2) r = Ray(Point(0, 0, 5), Vector(0, 0, 1)) i = Intersection(4, s2) comps = i.prepare_computations(r) c = w.shade_hit(comps) assert c == Color(0.1, 0.1, 0.1)
def csg(): s1 = Sphere() s1.transformation = translation(-0.375, 0, 0) s1.material.color = Color(1, 0, 0) s1.material.transparency = .8 s2 = Sphere() s2.transformation = translation(0.375, 0, 0) s2.material.pattern = GradientPattern(Color(1, 0, 0), Color(1, 1, 0)) s2.material.reflective = .8 s2.material.transparency = .8 c = Csg(OperationType.INTERSECTION, s1, s2) c.transformation = scaling(1, 1.5, 1) * rotation_y(-pi / 4) return c
def test_lighting_with_pattern_applied(self): m = Material() m.pattern = StripePattern(Color.white(), Color.black()) m.ambient = 1 m.diffuse = 0 m.specular = 0 eyev = Vector(0, 0, -1) normalv = Vector(0, 0, -1) light = PointLight(Point(0, 0, -10), Color.white()) c1 = m.lighting(Sphere(), light, Point(0.9, 0, 0), eyev, normalv, False) c2 = m.lighting(Sphere(), light, Point(1.1, 0, 0), eyev, normalv, False) assert c1 == Color.white() assert c2 == Color.black()
def test_stripe_pattern_alternates_in_x(self): pattern = StripePattern(Color.white(), Color.black()) assert pattern.pattern_at(Point(0, 0, 0)) == Color.white() assert pattern.pattern_at(Point(0.9, 0, 0)) == Color.white() assert pattern.pattern_at(Point(1, 0, 0)) == Color.black() assert pattern.pattern_at(Point(-0.1, 0, 0)) == Color.black() assert pattern.pattern_at(Point(-1, 0, 0)) == Color.black() assert pattern.pattern_at(Point(-1.1, 0, 0)) == Color.white()
def test_pattern_with_both_object_and_pattern_transformation(self): obj = Sphere() obj.transformation = scaling(2, 2, 2) pattern = test_pattern() pattern.transformation = translation(0.5, 1, 1.5) c = pattern.pattern_at_shape(obj, Point(2.5, 3, 3.5)) assert c == Color(0.75, 0.5, 0.25)
def test_default_material(self): m = Material() assert m.color == Color(1, 1, 1) assert m.ambient == 0.1 assert m.diffuse == 0.9 assert m.specular == 0.9 assert m.shininess == 200.0
def test_shade_hit_with_transparent_material(self, default_world): w = default_world floor = Plane() floor.transformation = translation(0, -1, 0) floor.material.transparency = 0.5 floor.material.refractive_index = 1.5 ball = Sphere() ball.material.color = Color(1, 0, 0) ball.material.ambient = 0.5 ball.transformation = translation(0, -3.5, -0.5) w.add(floor, ball) r = Ray(Point(0, 0, -3), Vector(0, -sqrt(2) / 2, sqrt(2) / 2)) xs = Intersections(Intersection(sqrt(2), floor)) comps = xs[0].prepare_computations(r, xs) color = w.shade_hit(comps, 5) assert color == Color(0.93642, 0.68642, 0.68642)
def plot_points_on_canvas(ps: List[Point], c: Canvas): blue = Color(0, 0, 1) for p in ps: x, y = int(p.x + c.width / 2), int(p.y + c.height / 2) print(f'x={x}, y={y}') if 0 <= x < c.width and 0 <= y < c.height: c.write_pixel(x, y, blue)
def test_refracted_color_with_opaque_surface(self, default_world): w = default_world shape = w.objects[0] r = Ray(Point(0, 0, -5), Vector(0, 0, 1)) xs = Intersections(Intersection(4, shape), Intersection(6, shape)) comps = xs[0].prepare_computations(r, xs) c = w.refracted_color(comps, 5) assert c == Color.black()
def test_shading_intersection(self, default_world): w = default_world r = Ray(Point(0, 0, -5), Vector(0, 0, 1)) shape = w.objects[0] i = Intersection(4, shape) comps = i.prepare_computations(r) c = w.shade_hit(comps) assert c == Color(0.38066, 0.47583, 0.2855)
def test_reflected_color_for_nonreflective_material(self, default_world): w = default_world r = Ray(Point(0, 0, 0), Vector(0, 0, 1)) shape = w.objects[1] shape.material.ambient = 1 i = Intersection(1, shape) comps = i.prepare_computations(r) color = w.reflected_color(comps) assert color == Color.black()
def test_render_world_with_camera(self, default_world): w = default_world c = Camera(11, 11, pi / 2) _from = Point(0, 0, -5) to = Point(0, 0, 0) up = Vector(0, 2, 0) c.transformation = view_transform(_from, to, up) image = c.render(w) assert image.pixel_at(5, 5) == Color(0.38066, 0.47583, 0.2855)
def test_splitting_long_lines_in_ppm(self): c = Canvas(10, 2) for x in range(c.width): for y in range(c.height): c.write_pixel(x, y, Color(1, 0.8, 0.6)) ppm = c.to_ppm() assert ''.join(ppm[3:]) == "255 204 153 255 204 153 255 204 153 255 204 153 255 204 153 255 204\n"\ "153 255 204 153 255 204 153 255 204 153 255 204 153\n" \ "255 204 153 255 204 153 255 204 153 255 204 153 255 204 153 255 204\n"\ "153 255 204 153 255 204 153 255 204 153 255 204 153\n"
def test_refracted_color_at_max_recursive_depth(self, default_world): w = default_world shape = w.objects[0] shape.material.transparency = 1.0 shape.material.refractive_index = 1.5 r = Ray(Point(0, 0, -5), Vector(0, 0, 1)) xs = Intersections(Intersection(4, shape), Intersection(6, shape)) comps = xs[0].prepare_computations(r, xs) c = w.refracted_color(comps, 0) assert c == Color.black()
def test_reflected_color_for_reflective_material(self, default_world): w = default_world shape = Plane() shape.material.reflective = 0.5 shape.transformation = translation(0, -1, 0) w.add(shape) r = Ray(Point(0, 0, -3), Vector(0, -sqrt(2) / 2, sqrt(2) / 2)) i = Intersection(sqrt(2), shape) comps = i.prepare_computations(r) color = w.reflected_color(comps) assert color == Color(0.19033, 0.23791, 0.14274)
def test_shade_hit_with_reflective_material(self, default_world): w = default_world shape = Plane() shape.material.reflective = 0.5 shape.transformation = translation(0, -1, 0) w.add(shape) r = Ray(Point(0, 0, -3), Vector(0, -sqrt(2) / 2, sqrt(2) / 2)) i = Intersection(sqrt(2), shape) comps = i.prepare_computations(r) color = w.shade_hit(comps) assert color == Color(0.87676, 0.92434, 0.82917)
def test_reflected_color_at_max_recursive_depth(self, default_world): w = default_world shape = Plane() shape.material.reflective = 0.5 shape.transformation = translation(0, -1, 0) w.add(shape) r = Ray(Point(0, 0, -3), Vector(0, -sqrt(2) / 2, sqrt(2) / 2)) i = Intersection(sqrt(2), shape) comps = i.prepare_computations(r) color = w.reflected_color(comps, 0) assert color == Color.black()
def test_refracted_color_under_total_internal_reflection(self, default_world): w = default_world shape = w.objects[0] shape.material.transparency = 1.0 shape.material.refractive_index = 1.5 r = Ray(Point(0, 0, sqrt(2) / 2), Vector(0, 1, 0)) xs = Intersections(Intersection(-sqrt(2) / 2, shape), Intersection(sqrt(2) / 2, shape)) # NOTE: this time you're inside the sphere, so you need # to look at the second intersection, xs[1], not xs[0] comps = xs[1].prepare_computations(r, xs) c = w.refracted_color(comps, 5) assert c == Color.black()
def test_refracted_color_with_refracted_ray(self, default_world): w = default_world a = w.objects[0] a.material.ambient = 1.0 a.material.pattern = test_pattern() b = w.objects[1] b.material.transparency = 1.0 b.material.refractive_index = 1.5 r = Ray(Point(0, 0, 0.1), Vector(0, 1, 0)) xs = Intersections(Intersection(-0.9899, a), Intersection(-0.4899, b), Intersection(0.4899, b), Intersection(0.9899, a)) comps = xs[2].prepare_computations(r, xs) c = w.refracted_color(comps, 5) assert c == Color(0, 0.99888, 0.04722)
def test_color_at_with_mutually_reflective_surfaces(self): w = World() w.light_source = PointLight(Point(0, 0, 0), Color.white()) lower = Plane() lower.material.reflective = 1 lower.transformation = translation(0, -1, 0) upper = Plane() upper.material.reflective = 1 upper.transformation = translation(0, 1, 0) w.add(lower, upper) r = Ray(Point(0, 0, 0), Vector(0, 1, 0)) # Avoid Infinite Recursion w.color_at(r) assert True
from math import pi from os import sep from raytracer.camera import Camera from raytracer.canvas import write_ppm_to_file from raytracer.lights import PointLight from raytracer.matrices import * from raytracer.obj_file import parse_obj_file from raytracer.scene import World from raytracer.tuples import Color, Point, Vector def teapot(): parser = parse_obj_file(f'..{sep}resources{sep}Sting-Sword-lowpoly.obj') return parser.obj_to_group() if __name__ == '__main__': world = World() world.add(teapot()) world.light_source = PointLight(Point(-5, 5, -5), Color.white()) camera = Camera(150, 100, pi / 3) camera.transformation = view_transform(Point(0, 1.5, -10), Point(0, 1, 0), Vector(0, 1, 0)) canvas = camera.render(world) write_ppm_to_file(canvas.to_ppm(), f'..{sep}..{sep}resources{sep}sting.ppm')
from math import pi from os import sep from raytracer.camera import Camera from raytracer.canvas import write_ppm_to_file from raytracer.lights import PointLight from raytracer.patterns import * from raytracer.matrices import scaling, rotation_y, rotation_x, translation, view_transform from raytracer.scene import World from raytracer.shapes import Sphere, Plane from raytracer.tuples import Color, Point, Vector if __name__ == '__main__': floor = Plane() floor.material.color = Color(.1, 1, .1) floor.material.reflective = 0.9 floor.material.transparency = 1 floor.material.refractive_index = 1.333 under = Sphere() under.transformation = translation(0, -.5, 0) * scaling(.25, .25, .25) under.material.color = Color(0, .8, 0) under.material.refractive_index = 1.5 under.material.ambient = .8 above = Sphere() above.transformation = translation(1, .5, 0) * scaling(.5, .5, .5) above.material.color = Color(.2, 0, 0) above.material.diffuse = .8 above.material.ambient = .5
from math import pi from os import sep from raytracer.camera import Camera from raytracer.canvas import write_ppm_to_file from raytracer.lights import PointLight from raytracer.materials import Material from raytracer.matrices import scaling, rotation_y, rotation_x, translation, view_transform from raytracer.scene import World from raytracer.shapes import Sphere, Plane from raytracer.tuples import Color, Point, Vector if __name__ == '__main__': floor = Plane() floor.material = Material() floor.material.color = Color(1, 0.9, 0.9) floor.material.specular = 0 middle = Sphere() middle.transformation = translation(-0.5, 1, 0.5) middle.material = Material() middle.material.color = Color(0.5, 0, 0) middle.material.diffuse = 0.7 middle.material.specular = 0.3 middle.material.reflective = 1 right = Sphere() right.transformation = translation(1.5, 0.5, -0.5) * scaling(0.5, 0.5, 0.5) right.material = Material() right.material.color = Color(0.2, 0.2, 0.8) right.material.diffuse = 0.7
from math import pi from os import sep from raytracer.camera import Camera from raytracer.canvas import write_ppm_to_file from raytracer.lights import PointLight from raytracer.materials import Material from raytracer.matrices import scaling, rotation_y, rotation_x, translation, view_transform from raytracer.patterns import CheckersPattern from raytracer.scene import World from raytracer.shapes import Sphere, Plane from raytracer.tuples import Color, Point, Vector if __name__ == '__main__': floor = Plane() floor.material = Material() floor.material.color = Color(1, 0.9, 0.9) floor.material.specular = 0 middle = Sphere() middle.transformation = translation(-0.5, 1, 0.5) middle.material = Material() middle.material.pattern = CheckersPattern(Color(0.1, 1, 0.5), Color(1, 0, 0)) middle.material.pattern.transformation = scaling(0.25, 0.25, 0.5) * rotation_y(pi / 4) middle.material.diffuse = 0.7 middle.material.specular = 0.3 right = Sphere() right.transformation = translation(1.5, 0.5, -0.5) * scaling(0.5, 0.5, 0.5) right.material = Material()
from math import pi from os import sep from raytracer.camera import Camera from raytracer.canvas import write_ppm_to_file from raytracer.lights import PointLight from raytracer.patterns import * from raytracer.matrices import scaling, rotation_x, rotation_y, rotation_z, translation, view_transform from raytracer.scene import World from raytracer.shapes import Cylinder, Plane from raytracer.tuples import Color, Point, Vector if __name__ == '__main__': floor = Plane() floor.material.color = Color(.8, .8, .8) floor.material.reflective = .2 cylinder = Cylinder(closed=True) cylinder.maximum = 0.25 cylinder.material.color = Color(.8, 0, 0) cylinder.material.reflective = .6 cylinder.transformation = translation(0, 1, 0) world = World() world.add(floor, cylinder) world.light_source = PointLight(Point(-10, 10, -10), Color.white()) camera = Camera(160, 120, pi / 3) camera.transformation = view_transform(Point(0, 1.5, -5), Point( 0, 1, 0), Vector(0, 1, 0)) * rotation_y(-pi / 4) * rotation_x(-pi / 6) canvas = camera.render(world)
def test_lighting_light_behind_surface(self, background): eyev = Vector(0, 0, -1) normalv = Vector(0, 0, -1) light = PointLight(Point(0, 0, 10), Color(1, 1, 1)) result = background['m'].lighting(Sphere(), light, background['position'], eyev, normalv) assert result == Color(0.1, 0.1, 0.1)