def render(width=200, height=100): hor_size = 4.0 ver_size = hor_size * 0.5 line = [] # Preload function line_append = line.append frame = [] # Preload function frame_append = frame.append nx = width ny = height lower_left_corner = vec3(-(hor_size / 2.0), -(ver_size / 2.0), -1.0) horizontal = vec3(hor_size, 0.0, 0.0) vertical = vec3(0.0, ver_size, 0.0) origin = vec3(0.0, 0.0, 0.0) for j in range(ny - 1, -1, -1): line.clear() v = float(j) / float(ny) for i in range(nx): u = float(i) / float(nx) r = ray(origin, lower_left_corner + u * horizontal + v * vertical) col = color(r) #pix = vec3(int(255.99 * col.r), int(255.99 * col.g), int(255.99 * col.b)) #line.append([pix.x, pix.y, pix.z]) # line.append([int(255.99 * col.r), int(255.99 * col.g), int(255.99 * col.b)]) line_append([ int(255.99 * col.r), int(255.99 * col.g), int(255.99 * col.b) ]) # frame.append(line.copy()) frame_append(line.copy()) return frame
def color(r): # bgColor = vec3(0.5, 0.7, 1.0) t = hit_sphere(vec3(0, 0, -1), 0.50, r) if t > 0.0: N = vec3.unit_vector(r.point_at_parameter(t) - vec3(0, 0, -1)) return 0.5 * vec3(N.x + 1, N.y + 1, N.z + 1) unit_direction = vec3.unit_vector(r.direction) t = 0.5 * (unit_direction.y + 1.0) return (1.0 - t) * vec3(1.0, 1.0, 1.0) + t * vec3(0.5, 0.7, 1.0)
def scatter(self, r_in, rec): reflected = reflect(r_in.direction(), rec.record[2]) attenuation = vec3(1.0, 1.0, 1.0) if (vec3.dot(r_in.direction(), rec.record[2]) > 0): outworld_normal = -rec.record[2] ni_over_nt = self.ref_idx cosine = self.ref_idx * vec3.dot(r_in.direction(), rec.record[2]) / r_in.direction().length() else: outworld_normal = rec.record[2] ni_over_nt = 1.0 / self.ref_idx cosine = -vec3.dot(r_in.direction(), rec.record[2]) / r_in.direction().length() isok, refracted = refract(r_in.direction(), outworld_normal, ni_over_nt) if isok: reflect_prob = schlick(cosine, self.ref_idx) else: reflect_prob = 1.0 if random.random() < reflect_prob: scattered = ray(rec.record[1], reflected) else: scattered = ray(rec.record[1], refracted) return True, scattered, attenuation
def color(r, world, depth): if isinstance(r, ray): infinity = float('inf') rec = hit_record() if world.hit(r, 0.001, infinity, rec): isscatter, s, a = rec.record[3].scatter(r, rec) if depth < 50 and isscatter: return a * color(s, world, depth+1) else: return vec3(0, 0, 0) else: unit_direction = vec3.unit_vector(r.direction()) t = 0.5*(unit_direction.y() + 1.0) return (1.0-t)*vec3(1.0, 1.0, 1.0) + t*vec3(0.5, 0.7, 1.0) else: return NotImplemented
def refract(v, n, ni_over_nt): uv = vec3.unit_vector(v) dt = vec3.dot(uv, n) discriminant = 1.0 - ni_over_nt*ni_over_nt*(1-dt*dt) refracted = vec3(0, 0, 0) if discriminant > 0: refracted = ni_over_nt*(uv - n*dt) - n*math.sqrt(discriminant) return True, refracted else: return False, refracted
def random_in_unit_disk(): while True: p = 2.0 * vec3(random.random(), random.random(), 0) - vec3(1, 1, 0) if vec3.dot(p, p) < 1: break return p
def __init__(self, t=0, p=vec3(0, 0, 0), normal=vec3(0, 0, 0), mat=0): if isinstance(p, vec3) and isinstance(normal, vec3) and isinstance( t, numbers.Real): self.record = [t, p, normal, mat] else: return NotImplemented
def random_in_unit_sphere(): while True: p = 2.0 * vec3(random.random(), random.random(), random.random()) - vec3(1, 1, 1) if p.length() < 1.0: break return p
def random_scene(): hlist = [] hlist.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.random() center = vec3(a+0.9*random.random(), 0.2, b+0.9*random.random()) if (center - vec3(4, 0.2, 0)).length() > 0.9: if choose_mat < 0.8: hlist.append(sphere(center, 0.2, lambertian(vec3(random.random(), random.random(), random.random())))) elif choose_mat < 0.95: hlist.append(sphere(center, 0.2, metal(vec3(0.5*(1+random.random()), 0.5*(1+random.random()), 0.5*(1+random.random())), 0.5*random.random()))) else: hlist.append(sphere(center, 0.2, dielectric(1.5))) hlist.append(sphere(vec3(0, 1, 0), 1.0, dielectric(1.5))) hlist.append(sphere(vec3(-4, 1, 0), 1.0, lambertian(vec3(0.4, 0.2, 0.1)))) hlist.append(sphere(vec3(4, 1, 0), 1.0, metal(vec3(0.7, 0.6, 0.5), 0.0))) return hittable_list(hlist)
unit_direction = vec3.unit_vector(r.direction()) t = 0.5*(unit_direction.y() + 1.0) return (1.0-t)*vec3(1.0, 1.0, 1.0) + t*vec3(0.5, 0.7, 1.0) else: return NotImplemented if __name__ == '__main__': file = r'.\out.ppm' nx = 200 ny = 100 ns = 100 world = random_scene() lookfrom = vec3(11, 5, 2) lookat = vec3(0, 0, -1) dist_to_focus = (lookfrom - lookat).length() aperture = 0.05 with open(file, 'w') as p: p.write("P3\n") p.write("{} {}\n".format(nx, ny)) p.write("255\n") for y in range(ny): print(y) for x in range(nx): col = vec3(0, 0, 0) cam = camera(lookfrom, lookat, vec3(0,1,0), 25, float(nx)/float(ny), aperture, dist_to_focus) for z in range(ns):