def make_world(): world = [] ground = Lambertian(Color(0.5, 0.5, 0.5)) world.append(Sphere(Point3(0, -1000, 0), 1000, ground)) num_balls = 2 for x in range(-num_balls, num_balls): for y in range(-num_balls, num_balls): mat = random() center = Point3(x + 0.9 * random(), 0.2, y + 0.9 * random()) if (SubtractVectors(center, Point3(4, 0.2, 0)).length() > 0.9): if mat < 0.8: color = Color(random(), random(), random()) sphere_mat = Lambertian(color) world.append(Sphere(center, 0.2, sphere_mat)) elif mat < 0.95: color = Color(random(), random(), random()) fuzz = random() * 0.5 sphere_mat = Metal(color, fuzz) world.append(Sphere(center, 0.2, sphere_mat)) else: sphere_mat = Dialectric(1.5) world.append(Sphere(center, 0.2, sphere_mat)) mat1 = Dialectric(1.5) world.append(Sphere(Point3(0, 1, 0), 1.0, mat1)) mat2 = Lambertian(Color(0.4, 0.2, 0.1)) world.append(Sphere(Point3(-4, 1, 0), 1.0, mat2)) mat3 = Metal(Color(0.7, 0.6, 0.5), 0.0) world.append(Sphere(Point3(4, 1, 0), 1.0, mat3)) return world
def random_scene(): l = [] l.append(Sphere(Vec3(0, -1000, -1), 1000, Lambertian(Vec3(0.5, 0.5, 0.5)))) for a in range(-11, 11): for b in range(-11, 11): choose_mat = random() center = Vec3(a + 0.9 * random(), 0.2, b + 0.9 * random()) if (center - Vec3(4, 0.2, 0)).length() > 0.9: if choose_mat < 0.8: #diffuse l.append( MovingSphere( center, center + Vec3(0.0, 0.5 * random(), 0.0), 0.0, 1.0, 0.2, Lambertian( Vec3(random() * random(), random() * random(), random() * random())))) elif choose_mat < 0.95: #metal l.append( Sphere( center, 0.2, Metal( Vec3(0.5 * (1 + random()), 0.5 * (1 + random()), 0.5 * (1 + random())), 0.5 * random()))) else: #glass l.append(Sphere(center, 0.2, Dielectric(1.5))) l.append(Sphere(Vec3(0, 1, 0), 1.0, Dielectric(1.5))) l.append(Sphere(Vec3(-4, 1, 0), 1.0, Lambertian(Vec3(0.4, 0.2, 0.1)))) l.append(Sphere(Vec3(4, 1, 0), 1.0, Metal(Vec3(0.7, 0.6, 0.5), 0.0))) return HitableList(l)
def random_scene(): hitables = [] hitables.append( Sphere(Vec3(0, -1000, 0), 1000, Lambertian(Vec3(0.5, 0.5, 0.5)))) for a in range(-11, 11): for b in range(-11, 11): choose_mat = random() center = Vec3(a + 0.9 * random(), 0.2, b + 0.9 * random()) if (center - Vec3(4, 0.2, 0)).length > 0.9: if choose_mat < 0.8: hitables.append( Sphere( center, 0.2, Lambertian( Vec3(random() * random(), random() * random(), random() * random())))) elif choose_mat < 0.95: hitables.append( Sphere( center, 0.2, Metal( Vec3(0.5 * (1 + random()), 0.5 * (1 + random()), 0.5 * (1 + random())), 0.5 * random()))) else: hitables.append(Sphere(center, 0.2, Dielectric(1.5))) hitables.append(Sphere(Vec3(0, 1, 0), 1.0, Dielectric(1.5))) hitables.append( Sphere(Vec3(-4, 1, 0), 1.0, Lambertian(Vec3(0.4, 0.2, 0.1)))) hitables.append(Sphere(Vec3(4, 1, 0), 1.0, Metal(Vec3(0.7, 0.6, 0.5), 0.0))) return HitableList(hitables)
def basic(self): self.lookfrom = np.array([3.0, 3.0, 2.0]) self.lookat = np.array([0.0, 0.0, -1.0]) self.vup = np.array([0.0, 1.0, 0.0]) self.vfov = 20.0 # self.aperature = 2.0 # self.focus_dist = ru.length(self.lookfrom - self.lookat) self.camera = Camera(self.img_width, self.img_height, self.lookfrom, self.lookat, self.vup, self.vfov, self.aperature, self.focus_dist) mat_ground = Lambertian(np.array([0.8, 0.8, 0.0])) mat_center = Lambertian(np.array([0.1, 0.2, 0.5])) mat_left = Dielectric(1.5) mat_right = Metal(np.array([0.8, 0.6, 0.2]), 0.0) self.world.add(Sphere(np.array([0.0, -100.5, -1.0]), 100, mat_ground)) self.world.add(Sphere(np.array([0.0, 0.0, -1.0]), 0.5, mat_center)) self.world.add(Sphere(np.array([-1.0, 0.0, -1.0]), 0.5, mat_left)) self.world.add(Sphere(np.array([-1.0, 0.0, -1.0]), -0.45, mat_left)) self.world.add(Sphere(np.array([1.0, 0.0, -1.0]), 0.5, mat_right)) self.world.add( BVHNode(self.world.objects, 0, len(self.world.objects), 0, 1)) self.background = np.array([0.7, 0.8, 1.0])
def main(): # image dimensions (pixel) nx = 200 ny = 100 # number of samples (rays) per pixel ns = 100 # define camera lookfrom = np.array([-3., 3., 3.]) lookat = np.array([0., 0., 0.]) vfov = np.pi/9 aperture = 1. focus_dist = np.linalg.norm(lookat - lookfrom) cam = Camera(lookfrom, lookat, np.array([0., 1., 0.]), vfov, nx / ny, aperture, focus_dist) # define scene geometry scene = SurfaceAssembly() scene.add_object(Sphere(np.array([ 0., 0., 0.]), 0.5, Lambertian(np.array([0.1, 0.2, 0.5])))) scene.add_object(Sphere(np.array([ 1., 0., 0.]), 0.5, Metal(np.array([0.8, 0.6, 0.2]), 1.0))) # imitate hollow glass sphere scene.add_object(Sphere(np.array([-1., 0., 0.]), 0.5, Dielectric(1.5))) scene.add_object(Sphere(np.array([-1., 0., 0.]), -0.45, Dielectric(1.5))) # large sphere imitating ground floor scene.add_object(Sphere(np.array([0., -100.5, 0.]), 100., Lambertian(np.array([0.8, 0.8, 0.0])))) # render image im = render_image(nx, ny, ns, scene, cam) imageio.imwrite('depth_of_field.png', im.transpose((1, 0, 2)))
def random_spheres(self): self.lookfrom = np.array([13.0, 2.0, 3.0]) self.lookat = np.array([0.0, 0.0, 0.0]) self.vfov = 20.0 self.aperature = 0.1 self.background = np.array([0.7, 0.8, 1.0]) self.camera = Camera(self.img_width, self.img_height, self.lookfrom, self.lookat, self.vup, self.vfov, self.aperature, self.focus_dist) mat_ground = Lambertian(np.array([0.5, 0.5, 0.5])) self.world.add(Sphere(np.array([0.0, -1000, 0.0]), 1000, mat_ground)) for a in range(-11, 11): for b in range(-11, 11): choose_mat = ru.get_random() center = np.array([ a + 0.9 * ru.get_random(), 0.2, b + 0.9 * ru.get_random() ]) if ru.length(center - np.array([4.0, 0.2, 0.0])) > 0.9: sphere_material: Material if choose_mat < 0.8: albedo = ru.get_random_point() * ru.get_random_point() sphere_material = Lambertian(albedo) elif choose_mat < 0.95: albedo = ru.get_random_point_in_range(0.5, 1.0) fuzz = ru.get_random_in_range(0.0, 0.5) sphere_material = Metal(albedo, fuzz) else: sphere_material = Dielectric(1.5) self.world.add(Sphere(center, 0.2, sphere_material)) mat1 = Dielectric(1.5) self.world.add(Sphere(np.array([0.0, 1.0, 0.0]), 1.0, mat1)) mat2 = Lambertian(np.array([0.4, 0.2, 0.1])) self.world.add(Sphere(np.array([-4.0, 1.0, 0.0]), 1.0, mat2)) mat3 = Metal(np.array([0.7, 0.6, 0.5]), 0.0) self.world.add(Sphere(np.array([4.0, 1.0, 0.0]), 1.0, mat3)) # BVH implementation self.world.add( BVHNode(self.world.objects, 0, len(self.world.objects), 0, 1))
def my_scene(self): self.vfov = 65 self.lookfrom = np.array([800, 180, 200]) self.lookat = np.array([200, 0, 800]) self.background = np.array([0, 0, 0]) self.camera = Camera(self.img_width, self.img_height, self.lookfrom, self.lookat, self.vup, self.vfov, self.aperature, self.focus_dist) light = DiffuseLight(np.array([1, 1, 1])) mirror = Metal(np.array([0.95, 0.95, 0.95]), 0) mat_ground = Lambertian(np.array([0.5, 0.5, 0.5])) glass = Dielectric(2.0) mat_sphere = Lambertian(np.array([0.8, 0.8, 0.8])) self.world.add(XZRectangle(200, 800, 200, 800, 0, mat_ground)) self.world.add(XYRectangle(425, 575, 0, 100, 700, light)) self.world.add(XYRectangle(425, 575, 0, 100, 310, light)) self.world.add(YZRectangle(0, 250, 200, 800, 200, mirror)) self.world.add(YZRectangle(0, 250, 200, 800, 800, mirror)) self.world.add(XYRectangle(200, 800, 0, 250, 800, mirror)) self.world.add(XYRectangle(200, 800, 0, 250, 200, mirror)) for x in range(470, 531, 30): for z in range(535, 474, -30): self.world.add(Sphere(np.array([x, 15, z]), 15, glass)) for x in range(485, 516, 30): for z in range(520, 489, -30): self.world.add( Sphere(np.array([x, 15 * (1 + np.sqrt(3)), z]), 15, glass)) self.world.add( Sphere(np.array([500, 15 * (1 + 2 * np.sqrt(3)), 505]), 15, glass)) self.world.add(Sphere(np.array([500, 15, 445]), 15, mirror)) self.world.add(Sphere(np.array([500, 15, 565]), 15, mirror)) self.world.add(Sphere(np.array([440, 15, 505]), 15, mat_sphere)) self.world.add(Sphere(np.array([560, 15, 505]), 15, mat_sphere)) dist = 15 * np.sqrt(2) self.world.add( Sphere(np.array([470 - dist, 15, 535 + dist]), 15, light)) self.world.add( Sphere(np.array([530 + dist, 15, 535 + dist]), 15, light)) self.world.add( Sphere(np.array([470 - dist, 15, 475 - dist]), 15, light)) self.world.add( Sphere(np.array([530 + dist, 15, 475 - dist]), 15, light)) self.world.add( BVHNode(self.world.objects, 0, len(self.world.objects), 0, 1))
def get_world() -> World: world = [] glass = Dielectric(1.5) # Ground ground_mat = Lambertian(Color(0.5, 0.5, 0.5)) world.append(Sphere(Vector(0, -1000, 0), 1000, ground_mat)) # Marbles for x in range(-11, 11): for z in range(-11, 11): choose_material = random() material: Material center = Vector(x + .9 * random(), .2, z + .9 * random()) if (center - Vector(4, .2, 0)).norm() <= .9: continue if choose_material < .8: # Diffuse albedo = Color(*(random(3) * random(3))) material = Lambertian(albedo) elif choose_material < .95: # Metal albedo = Color(*(random(3) * .5 + .5)) fuzz = random() * .4 material = Metal(albedo, fuzziness=fuzz) else: # Glass material = glass world.append(Sphere(center, .2, material)) # Big Spheres world.append(Sphere(Vector(4, 1, 0), 1.0, glass)) world.append(Sphere(Vector(-4, 1, 0), 1.0, Lambertian(Color(.6, .1, .1)))) world.append(Sphere(Vector(0, 1, 0), 1.0, Metal(Color(.7, .6, .5)))) return World(world)
def main(): # image dimensions (pixel) nx = 200 ny = 100 # number of samples (rays) per pixel ns = 100 # define camera lookfrom = np.zeros(3) lookat = np.array([0., 0., -1.]) vfov = np.pi / 2 aperture = 0. focus_dist = 1. cam = Camera(lookfrom, lookat, np.array([0., 1., 0.]), vfov, nx / ny, aperture, focus_dist) # define scene geometry scene = SurfaceAssembly() scene.add_object( Sphere(np.array([0., 0., -1.]), 0.5, Lambertian(np.array([0.8, 0.3, 0.3])))) scene.add_object( Sphere(np.array([1., 0., -1.]), 0.5, Metal(np.array([0.8, 0.6, 0.2]), 1.0))) scene.add_object( Sphere(np.array([-1., 0., -1.]), 0.5, Metal(np.array([0.8, 0.8, 0.8]), 0.3))) # large sphere imitating ground floor scene.add_object( Sphere(np.array([0., -100.5, -1.]), 100., Lambertian(np.array([0.8, 0.8, 0.0])))) # render image im = render_image(nx, ny, ns, scene, cam) imageio.imwrite('metal_spheres.png', im.transpose((1, 0, 2)))
def get_small_world() -> World: mat_ground = Lambertian(Color(.8, .8, .3)) ground = Sphere(Vector(0, -100.5, -1), 100, mat_ground) mat_center = Lambertian(Color(.7, .3, .3)) center = Sphere(Vector(0, 0, -1), .5, mat_center) mat_left = Metal(Color(.8, .8, .8)) left = Sphere(Vector(-1, 0, -1), .5, mat_left) mat_right = Dielectric(1.5) right = Sphere(Vector(1, 0, -1), .5, mat_right) return World([ground, center, left, right])
def random_scene(): """Generate a random scene.""" result = [] sphere = Sphere(Vec3(0, -1000, 0), 1000, Lambertian(Vec3(0.5, 0.5, 0.5))) result.append(sphere) for a in range(-11, 11): for b in range(-11, 11): choose_mat = random() center = Vec3(a + 0.9 * random(), 0.2, b + 0.9 * random()) if (center - Vec3(4, 0.2, 0)).length > 0.9: if choose_mat < 0.8: # make diffuse sphere = Sphere( center, 0.2, Lambertian( Vec3(random() * random(), random() * random(), random() * random()))) elif choose_mat < 0.95: # make metallic sphere = Sphere( center, 0.2, Metal( Vec3(0.5 * (1 + random()), 0.5 * (1 + random()), 0.5 * (1 + random())), 0.5 * random())) else: # make glassy sphere = Sphere(center, 0.2, Dielectric(1.5)) result.append(sphere) result.append(Sphere(Vec3(0, 1, 0), 1.0, Dielectric(1.5))) result.append(Sphere(Vec3(-4, 1, 0), 1.0, Lambertian(Vec3(0.4, 0.2, 0.1)))) result.append(Sphere(Vec3(4, 1, 0), 1.0, Metal(Vec3(0.7, 0.6, 0.5), 0.0))) return Hitable_List(result)
def main(): # image dimensions (pixel) nx = 1200 ny = 800 # number of samples (rays) per pixel ns = 10 # define camera lookfrom = np.array([13., 2., 3.]) lookat = np.zeros(3) vfov = np.pi / 9 aperture = 0.1 focus_dist = 10.0 cam = Camera(lookfrom, lookat, np.array([0., 1., 0.]), vfov, nx / ny, aperture, focus_dist) # define scene geometry scene = SurfaceAssembly() # three large spheres scene.add_object( Sphere(np.array([4., 1., 0.]), 1.0, Metal(np.array([0.7, 0.6, 0.5]), 0.))) scene.add_object(Sphere(np.array([0., 1., 0.]), 1.0, Dielectric(1.5))) scene.add_object( Sphere(np.array([-4., 1., 0.]), 1.0, Lambertian(np.array([0.4, 0.2, 0.1])))) # smaller spheres with random parameters for a in range(-11, 12): for b in range(-11, 12): center = np.array([ a + 0.9 * np.random.rand(), 0.2 + 0.1 * np.random.rand(), b + 0.9 * np.random.rand() ]) # random choice between diffusive, metal or dielectric (glass) choose_mat = np.random.choice(3, p=[0.8, 0.15, 0.05]) if choose_mat == 0: # diffusive scene.add_object( Sphere( center, 0.2, Lambertian(np.random.triangular(0., 0.2, 1., size=3)))) elif choose_mat == 1: # metal scene.add_object( Sphere( center, 0.2, Metal(0.5 * (1 + np.random.rand(3)), 0.5 * np.random.rand()))) else: # dielectric (glass) scene.add_object(Sphere(center, 0.2, Dielectric(1.5))) # huge sphere imitating ground floor scene.add_object( Sphere(np.array([0., -1000., 0.]), 1000., Lambertian(np.array([0.5, 0.5, 0.5])))) # render image im = render_image(nx, ny, ns, scene, cam) imageio.imwrite('random_scene.png', im.transpose((1, 0, 2)))
Vec3(0, -100, -1), # Radius of the sphere 100, # Material of the sphere (lambertian is just diffuse) Lambertian( # Color of the material (RGB) Vec3(0.4, 0.4, 0.4)), )) world.objects.append( Sphere( Vec3(0, 1, -3), 1, # Metal sphere Metal( # Tint of the metal Vec3(0.8, 0.8, 0.8), # "Blurriness" 0.1, ), )) world.objects.append( Sphere( Vec3(0.5, 0.5, 0.4), 0.5, # Transperent sphere Dialectric( # Refraction coefficient (1 for air) 1.5), )) world.objects.append( Sphere(Vec3(0, 0.8, -1), 0.8, Lambertian(Vec3(0.7, 0.3, 0.2)))) # Add more objects here!