def reflected_color(self, hit, remaining=5): if remaining <= 0: return color(0, 0, 0) if hit.object.material.reflective == 0.0: return color(0, 0, 0) reflect_ray = Ray(hit.over_point, hit.reflectv) reflect_color = self.color_at(reflect_ray, remaining - 1) return multiply(reflect_color, hit.object.material.reflective)
def from_yaml(cls, data): pattern_data = data['pattern'] color_a = pattern_data['colors'][0] color_b = pattern_data['colors'][1] pattern = cls(color(color_a[0], color_a[1], color_a[2]), color(color_b[0], color_b[1], color_b[2])) if 'transform' in pattern_data: pattern.set_transform(transform_from_yaml(pattern_data)) return pattern
def color_at(self, ray, remaining=5): intersections = self.intersect(ray) hit_intersection = hit_at(intersections) if hit_intersection is None: return color(0, 0, 0) shape_hit = Hit(hit_intersection, ray, intersections) return self.shade_hit(shape_hit, remaining)
def from_yaml(cls, data): values = data['at'] position = point(values[0], values[1], values[2]) values = data['intensity'] intensity = color(values[0], values[1], values[2]) return cls(position, intensity)
def default(cls): world = cls() world.add_light(PointLight(point(-10, 10, -10), color(1, 1, 1))) sphere1 = Sphere() mat = Material() mat.color = color(0.8, 1.0, 0.6) mat.diffuse = 0.7 mat.specular = 0.2 sphere1.material = mat sphere2 = Sphere() sphere2.set_transform(scaling(0.5, 0.5, 0.5)) world.objects.append(sphere1) world.objects.append(sphere2) return world
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.reflective = 0.0 self.transparency = 0.0 self.refractive_index = 1.0 self.pattern = None
def main(): canvas_pixels = 500 canvas = Canvas(canvas_pixels, canvas_pixels) shape = Sphere() # assign material shape.material = Material() shape.material.color = color(1, 0.2, 1) light_position = point(-10, 10, -10) light_color = color(1, 1, 1) light = PointLight(light_position, light_color) ray_origin = point(0, 0, -5) wall_z = 10 wall_size = 7.0 pixel_size = wall_size / canvas_pixels half = wall_size / 2 for y in range(canvas_pixels): world_y = half - pixel_size * y for x in range(canvas_pixels): world_x = -half + pixel_size * x pos = point(world_x, world_y, wall_z) r = Ray(ray_origin, normalize(subtract(pos, ray_origin))) xs = shape.intersect(r) shape_hit = hit(xs) if shape_hit is not None: hit_point = r.position_at(shape_hit.t) normal = shape_hit.object.normal_at(hit_point) eye = negate(r.direction) px_color = lighting(shape_hit.object.material, shape_hit.object, light, hit_point, eye, normal) canvas.set_pixel(x, y, px_color) with open('render_phong_sphere.ppm', 'w') as out_file: out_file.write(canvas.to_ppm())
def refracted_color(self, hit, remaining=5): if remaining <= 0: return color(0, 0, 0) if hit.object.material.transparency == 0.0: return color(0, 0, 0) n_ratio = hit.n1 / hit.n2 cos_i = dot(hit.eyev, hit.normalv) sin2_t = n_ratio**2 * (1 - cos_i**2) if sin2_t > 1.0: return color(0, 0, 0) cos_t = sqrt(1.0 - sin2_t) direction = subtract(multiply(hit.normalv, (n_ratio * cos_i - cos_t)), multiply(hit.eyev, n_ratio)) refract_ray = Ray(hit.under_point, direction) return multiply(self.color_at(refract_ray, remaining - 1), hit.object.material.transparency)
def main(): p = dict(position=point(0, 1, 0), velocity=multiply(normalize(vector(1, 1.8, 0)), 11.25)) e = dict(gravity=vector(0, -0.1, 0), wind=vector(-0.01, 0, 0)) c = Canvas(900, 550) while p['position'][1] > 0.0: print( f"position {p['position'][0]}, {p['position'][1]}, {p['position'][2]}" ) c.set_pixel(round(p['position'][0]), c.height - round(p['position'][1]), color(0.0, 1.0, 0.0)) p = tick(e, p) with open('cannon.ppm', 'w') as out_file: out_file.write(c.to_ppm())
def main(): c = Canvas(500, 500) p = point(0, 0, 1) translate = translation(250, 0, 250) scale = scaling(100, 0, 100) for h in range(12): r = rotation_y(h * pi / 6) transform = multiply_matrix(translate, multiply_matrix(scale, r)) p2 = multiply_tuple(transform, p) print(f"position ({p2[0]}, {p2[1]}, {p2[2]})") c.set_pixel(round(p2[0]), c.height - round(p2[2]), color(0.0, 1.0, 0.0)) with open('clock.ppm', 'w') as out_file: out_file.write(c.to_ppm())
def set_shape_attributes(shape, table): for row in table: if row['variable'] == 'material.color' and row['value'] == '(1, 0, 0)': shape.material.color = color(1, 0, 0) if row['variable'] == 'material.ambient': shape.material.ambient = float(row['value']) if row['variable'] == 'material.transparency': shape.material.transparency = float(row['value']) if row['variable'] == 'material.reflective': shape.material.reflective = float(row['value']) if row['variable'] == 'material.refractive_index': shape.material.refractive_index = float(row['value']) if row['variable'] == 'transform': shape.set_transform(TRANSFORMATIONS.get(row['value']))
def shade_hit(self, hit, remaining=5): surface = color(0, 0, 0) for light in self.lights: light_intensity = light.intensity_at(hit.over_point, self) surface = add( surface, lighting(hit.object.material, hit.object, light, hit.point, hit.eyev, hit.normalv, light_intensity)) reflected = self.reflected_color(hit, remaining) refracted = self.refracted_color(hit, remaining) material = hit.object.material if material.reflective > 0 and material.transparency > 0: reflectance = hit.schlick() return add(add(surface, multiply(reflected, reflectance)), multiply(refracted, (1 - reflectance))) return add(add(surface, reflected), refracted)
def from_yaml(cls, data): values = data['corner'] corner = point(values[0], values[1], values[2]) values = data['uvec'] uvec = vector(values[0], values[1], values[2]) usteps = data['usteps'] values = data['vvec'] vvec = vector(values[0], values[1], values[2]) vsteps = data['vsteps'] values = data['intensity'] intensity = color(values[0], values[1], values[2]) light = cls(corner, uvec, usteps, vvec, vsteps, intensity) if 'jitter' in data and data['jitter']: light.jitter_by = RandomSequence() return light
def main(): canvas_pixels = 400 canvas = Canvas(canvas_pixels, canvas_pixels) red = color(1, 0, 0) shape = Sphere() # shrink it along the y axis #shape.set_transform(scaling(1, 0.5, 1)) # shrink it along the x axis #shape.set_transform(scaling(0.5, 1, 1)) # shrink it, and rotate it! # shape.set_transform(multiply_matrix(rotation_z(pi / 4), scaling(0.5, 1, # 1))) # shrink it, and skew it! # shape.set_transform( # multiply_matrix(shearing(1, 0, 0, 0, 0, 0), scaling(0.5, 1, 1))) ray_origin = point(0, 0, -5) wall_z = 10 wall_size = 7.0 pixel_size = wall_size / canvas_pixels half = wall_size / 2 for y in range(canvas_pixels): world_y = half - pixel_size * y for x in range(canvas_pixels): world_x = -half + pixel_size * x pos = point(world_x, world_y, wall_z) r = Ray(ray_origin, normalize(subtract(pos, ray_origin))) xs = shape.intersect(r) if hit(xs) is not None: canvas.set_pixel(x, y, red) with open('render_sphere.ppm', 'w') as out_file: out_file.write(canvas.to_ppm())
def from_yaml(cls, data): material = cls() material_data = data['material'] if 'pattern' in material_data: pattern_type = material_data['pattern']['type'] parse_method = _TYPE_MAP.get(pattern_type) if parse_method is None: raise ValueError(f"Unknown type '{pattern_type}'") material.pattern = parse_method(material_data) if 'color' in material_data: values = material_data['color'] material.color = color(values[0], values[1], values[2]) if 'ambient' in material_data: material.ambient = material_data['ambient'] if 'diffuse' in material_data: material.diffuse = material_data['diffuse'] if 'specular' in material_data: material.specular = material_data['specular'] if 'shininess' in material_data: material.shininess = material_data['shininess'] if 'reflective' in material_data: material.reflective = material_data['reflective'] if 'transparency' in material_data: material.transparency = material_data['transparency'] if 'refractive-index' in material_data: material.refractive_index = material_data['refractive-index'] return material
def step_set_light_to_area_light(context, vsteps, usteps, red, green, blue): context.light = AreaLight(context.corner, context.v1, vsteps, context.v2, usteps, color(red, green, blue))
def step_create_point_light_direct(context, px, py, pz, red, green, blue): context.light = PointLight(point(px, py, pz), color(red, green, blue))
def step_impl(context): assert_tuple(hadamard(context.c1, context.c2), color(0.9, 0.2, 0.04))
def step_impl(context): assert multiply(context.c, 2) == color(0.4, 0.6, 0.8)
def step_impl(context): actual = subtract(context.c1, context.c2) assert_tuple(actual, color(0.2, 0.5, 0.5))
def step_impl(context, r, g, b): context.c = color(r, g, b)
def step_impl(context): assert add(context.c1, context.c2) == color(1.6, 0.7, 1.0)
def step_assert_c_equals_color(context, red, green, blue): assert_tuple(context.c, color(red, green, blue))
def step_assert_light_intensity_equals_color(context, red, green, blue): assert_tuple(context.light.intensity, color(red, green, blue))
def step_assert_material_color_of_s_equals_color(context, red, green, blue): assert_tuple(context.s.material.color, color(red, green, blue))
def step_set_pattern_of_m(context): context.m.pattern = StripePattern(color(1, 1, 1), color(0, 0, 0))
def step_set_color_of_m(context, red, green, blue): context.m.color = color(red, green, blue)
def step_assert_pattern_of_m_is_gradient_pattern(context): assert isinstance(context.m.pattern, GradientPattern), \ f"{context.m.pattern.__class__.__name__} is not GradientPattern" assert_tuple(context.m.pattern.color_a, color(1, 1, 1)) assert_tuple(context.m.pattern.color_b, color(0, 0, 0))
def step_assert_material_color_of_object_at_index(context, index, red, green, blue): assert_tuple(context.w.objects[index].material.color, color(red, green, blue))
def step_assert_color_of_m(context, red, green, blue): assert_tuple(context.m.color, color(red, green, blue))