def test_a_gradient_linearly_interpolates_between_colors(): # Given pattern = GradientPattern(WHITE, BLACK) # Then assert pattern.pattern_at(Point(0.25, 0, 0)) == Color(0.75, 0.75, 0.75) assert pattern.pattern_at(Point(0.5, 0, 0)) == Color(0.5, 0.5, 0.5) assert pattern.pattern_at(Point(0.75, 0, 0)) == Color(0.25, 0.25, 0.25)
def test_creating_a_canvas(): # Given c = Canvas(10, 20) # Then assert c.width == 10 assert c.height == 20 for h in range(20): for w in range(10): assert c.pixels[h][w] == Color(0, 0, 0) b = Color(0, 0, 0) assert c.pixels == \ [ [b, b, b, b, b, b, b, b, b, b], [b, b, b, b, b, b, b, b, b, b], [b, b, b, b, b, b, b, b, b, b], [b, b, b, b, b, b, b, b, b, b], [b, b, b, b, b, b, b, b, b, b], [b, b, b, b, b, b, b, b, b, b], [b, b, b, b, b, b, b, b, b, b], [b, b, b, b, b, b, b, b, b, b], [b, b, b, b, b, b, b, b, b, b], [b, b, b, b, b, b, b, b, b, b], [b, b, b, b, b, b, b, b, b, b], [b, b, b, b, b, b, b, b, b, b], [b, b, b, b, b, b, b, b, b, b], [b, b, b, b, b, b, b, b, b, b], [b, b, b, b, b, b, b, b, b, b], [b, b, b, b, b, b, b, b, b, b], [b, b, b, b, b, b, b, b, b, b], [b, b, b, b, b, b, b, b, b, b], [b, b, b, b, b, b, b, b, b, b], [b, b, b, b, b, b, b, b, b, b], ]
def test_the_color_when_a_ray_misses__only_negative_intersection_t(): w = World() w.light = PointLight(Point(-10, 10, -10), Color(1, 1, 1)) w.objects = [Plane()] r = Ray(Point(0, 10, 0), Vector(0, 1, 1).normalize()) c = w.color_at(r) assert c == Color(0, 0, 0)
def color_at(self, ray, remaining=4): xs = self.intersect_world(ray) if not xs: return Color(0, 0, 0) hit = xs.hit() if not hit: return Color(0, 0, 0) comps = hit.prepare_computations(ray, xs) return self.shade_hit(comps, remaining)
def test_shading_an_intersection_from_the_inside(): # Given w = default_world() w.light = PointLight(Point(0, 0.25, 0), Color(1, 1, 1)) r = Ray(Point(0, 0, 0), Vector(0, 0, 1)) shape = w.objects[1] i = Intersection(0.5, shape) # When comps = i.prepare_computations(r) c = w.shade_hit(comps) # Then assert c == Color(0.90498, 0.90498, 0.90498)
def test_lighting_with_the_eye_between_light_and_surface_eye_offset_45degree(): # Given m = Material() position = Point(0, 0, 0) eyev = Vector(0, sqrt(2) / 2, sqrt(2) / 2) normalv = Vector(0, 0, -1) light = PointLight(Point(0, 0, -10), Color(1, 1, 1)) object = Sphere() # When result = m.lighting(object, light, position, eyev, normalv) # Then assert result == Color(1.0, 1.0, 1.0)
def test_lighting_with_the_light_behind_the_surface(): # Given m = Material() position = Point(0, 0, 0) eyev = Vector(0, 0, -1) normalv = Vector(0, 0, -1) light = PointLight(Point(0, 0, 10), Color(1, 1, 1)) object = Sphere() # When result = m.lighting(object, light, position, eyev, normalv) # Then assert result == Color(0.1, 0.1, 0.1)
def test_lighting_with_the_eye_in_the_path_of_the_reflection_vector(): # Given m = Material() position = Point(0, 0, 0) eyev = Vector(0, -sqrt(2) / 2, -sqrt(2) / 2) normalv = Vector(0, 0, -1) light = PointLight(Point(0, 10, -10), Color(1, 1, 1)) object = Sphere() # When result = m.lighting(object, light, position, eyev, normalv) # Then assert result == Color(1.6364, 1.6364, 1.6364)
def test_lighting_with_the_eye_opposite_surface_light_offset_45degree(): # Given m = Material() position = Point(0, 0, 0) eyev = Vector(0, 0, -1) normalv = Vector(0, 0, -1) light = PointLight(Point(0, 10, -10), Color(1, 1, 1)) object = Sphere() # When result = m.lighting(object, light, position, eyev, normalv) # Then assert result == Color(0.7364, 0.7364, 0.7364)
def default_world(): light = PointLight(Point(-10, 10, -10), Color(1, 1, 1)) 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.transform = scaling(0.5, 0.5, 0.5) w = World() w.light = light w.objects = [s1, s2] return w
def test_default_world(): # Given light = PointLight(Point(-10, 10, -10), Color(1, 1, 1)) 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.transform = scaling(0.5, 0.5, 0.5) # When w = default_world() # Then assert w.light == light assert s1 in w.objects assert s2 in w.objects
def reflected_color(self, comps, remaining=4): if comps.object.material.reflective == 0 or remaining <= 0: return Color(0, 0, 0) reflect_ray = Ray(comps.over_point, comps.reflectv) color = self.color_at(reflect_ray, remaining - 1) return color * comps.object.material.reflective
def test__shade_hit__is_given_an_intersection_in_shadow(): # Given w = World() w.light = PointLight(Point(0, 0, -10), Color(1, 1, 1)) s1 = Sphere() w.objects.append(s1) s2 = Sphere() s2.transform = translation(0, 0, 10) w.objects.append(s2) r = Ray(Point(0, 0, 5), Vector(0, 0, 1)) i = Intersection(4, s2) # When comps = i.prepare_computations(r) c = w.shade_hit(comps) # Then assert c == Color(0.1, 0.1, 0.1)
def lighting(self, object, light, point, eyev, normalv, in_shadow=False): if self.pattern: color = self.pattern.pattern_at_shape(object, point) else: color = self.color effective_color = color * light.intensity ambient = effective_color * self.ambient if in_shadow: return ambient lightv = (light.position - point).normalize() light_dot_normal = lightv.dot(normalv) black = Color(0, 0, 0) if light_dot_normal < 0: diffuse = black specular = black else: diffuse = effective_color * self.diffuse * light_dot_normal reflectv = (-lightv).reflect(normalv) reflect_dot_eye = reflectv.dot(eyev) if reflect_dot_eye <= 0: specular = black else: factor = pow(reflect_dot_eye, self.shininess) specular = light.intensity * self.specular * factor return ambient + diffuse + specular
def test_colors_are_red_green_blue_tuples(): # Given c = Color(-0.5, 0.4, 1.7) # Then assert c.red == -0.5 assert c.green == 0.4 assert c.blue == 1.7
def test_constructing_the_ppm_pixel_data(): # Given c = Canvas(5, 3) c1 = Color(1.5, 0, 0) c2 = Color(0, 0.5, 0) c3 = Color(-0.5, 0, 1) # When c.write_pixel(0, 0, c1) c.write_pixel(2, 1, c2) c.write_pixel(4, 2, c3) ppm = c.to_ppm() # Then assert ppm.split("\n")[3:6] == \ ["255 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0 0 0 0 0 0 0 128 0 0 0 0 0 0 0", "0 0 0 0 0 0 0 0 0 0 0 0 0 0 255"]
def test_the_color_when_a_ray_hits(): # Given w = default_world() r = Ray(Point(0, 0, -5), Vector(0, 0, 1)) # When c = w.color_at(r) # Then assert c == Color(0.38066, 0.47583, 0.2855)
def test_the_color_when_a_ray_misses(): # Given w = default_world() r = Ray(Point(0, 0, -5), Vector(0, 1, 0)) # When c = w.color_at(r) # Then assert c == Color(0, 0, 0)
def test_lighting_with_a_pattern_applied(): # Given m = Material() m.pattern = StripePattern(Color(1, 1, 1), Color(0, 0, 0)) 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(1, 1, 1)) object = Sphere() # When c1 = m.lighting(object, light, Point(0.9, 0, 0), eyev, normalv) c2 = m.lighting(object, light, Point(1.1, 0, 0), eyev, normalv) # Then assert c1 == Color(1, 1, 1) assert c2 == Color(0, 0, 0)
def test_a_pattern_with_a_pattern_transformation(): # Given shape = Sphere() pattern = MockPattern() pattern.transform = scaling(2, 2, 2) # When c = pattern.pattern_at_shape(shape, Point(2, 3, 4)) # Then assert c == Color(1, 1.5, 2)
def refracted_color(self, comps, remaining): if remaining == 0 or comps.object.material.transparency == 0: return Color(0, 0, 0) n_ratio = comps.n1 / comps.n2 cos_i = comps.eyev.dot(comps.normalv) sin2_t = n_ratio**2 * (1 - cos_i**2) if sin2_t > 1: return Color(0, 0, 0) cos_t = sqrt(1.0 - sin2_t) direction = comps.normalv * \ (n_ratio * cos_i - cos_t) - comps.eyev * n_ratio refracted_ray = Ray(comps.under_point, direction) color = self.color_at(refracted_ray, remaining - 1) return color * comps.object.material.transparency
def test_the_default_material(): # Given m = Material() # Then 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_a_point_light_has_a_position_and_intensity(): # Given intensity = Color(1, 1, 1) position = Point(0, 0, 0) # When light = PointLight(position, intensity) # Then assert light.position == position assert light.intensity == intensity
def test_writing_pixels_to_a_canvas(): # Given c = Canvas(10, 20) red = Color(1, 0, 0) # When c.write_pixel(2, 3, red) # Then assert c.pixel_at(2, 3) == red assert c.pixels[3][2] == red
def test_a_pattern_with_both_an_object_and_a_pattern_transformation(): # Given shape = Sphere() shape.transform = scaling(2, 2, 2) pattern = MockPattern() pattern.transform = translation(0.5, 1, 1.5) # When c = pattern.pattern_at_shape(shape, Point(2.5, 3, 3.5)) # Then assert c == Color(0.75, 0.5, 0.25)
def __init__(self): self.color = Color(1, 1, 1) self.ambient = 0.1 self.diffuse = 0.9 self.specular = 0.9 self.shininess = 200.0 self.pattern = None self.reflective = 0.0 self.transparency = 0.0 self.refractive_index = 1.0
def test_the_refracted_color_with_an_opaque_surface(): # Given 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)) # When comps = xs[0].prepare_computations(r, xs) c = w.refracted_color(comps, 5) # Then assert c == Color(0, 0, 0)
def test_shading_an_intersection(): # Given w = default_world() r = Ray(Point(0, 0, -5), Vector(0, 0, 1)) shape = w.objects[0] i = Intersection(4, shape) # When comps = i.prepare_computations(r) c = w.shade_hit(comps) # Then assert c == Color(0.38066, 0.47583, 0.2855)
def test_the_reflected_color_for_a_nonreflective_material(): # Given w = default_world() r = Ray(Point(0, 0, 0), Vector(0, 0, 1)) shape = Sphere() shape.material.ambient = 1 i = Intersection(1, shape) # When comps = i.prepare_computations(r) color = w.reflected_color(comps) # Then assert color == Color(0, 0, 0) # black
def test_rendering_a_world_with_a_camera(): # Given w = default_world() c = Camera(11, 11, pi / 2) f = Point(0, 0, -5) to = Point(0, 0, 0) up = Vector(0, 1, 0) c.transform = view_transform(f, to, up) # When image = c.render(w) # Then assert image.pixel_at(5, 5) == Color(0.38066, 0.47583, 0.2855)