Beispiel #1
0
    def random_in_unit_sphere() -> Vec3:
        p = Vec3(random(), random(), random()) * 2.0 - Vec3(1, 1, 1)

        while p.length()**2 >= 1:
            p = Vec3(random(), random(), random()) * 2.0 - Vec3(1, 1, 1)

        return p
Beispiel #2
0
 def scatter(self, r_in: Ray, hitPoint: Vec3, hitNormal: Vec3, \
             attenuation: Vec3, scattered: Ray):
     reflected = super().reflect(r_in.direction.unit(), hitNormal)
     scattered.set(
         Ray(hitPoint,
             reflected + super().random_in_unit_sphere() * self.fuzz))
     attenuation.set(self.albedo)
     return Vec3.dot(scattered.direction, hitNormal) > 0
Beispiel #3
0
 def refract(v: Vec3, n: Vec3, ni_over_nt: float, refracted: Vec3) -> bool:
     uv = v.unit()
     dt = Vec3.dot(uv, n)
     discriminant = 1 - ni_over_nt * ni_over_nt * (1 - dt * dt)
     if discriminant > 0:
         refracted.set((uv - n * dt) * ni_over_nt - n * (discriminant**0.5))
         return True
     else:
         return False
Beispiel #4
0
    def hit(self, r: Ray, t_min: float, t_max: float, rec: HitRecord):
        hit_anything = False
        closest_so_far = t_max

        temp_rec = HitRecord(0, Vec3(0, 0, 0), Vec3(0, 0, 1))

        for item in self.hit_list:
            if item.hit(r, t_min, closest_so_far, temp_rec):
                hit_anything = True
                closest_so_far = temp_rec.t
                rec.set(temp_rec)
        return hit_anything
Beispiel #5
0
    def __init__(self, look_from: Vec3, look_at: Vec3, up: Vec3, \
                vert_FOV: float, aspect_ratio: float, \
                aperture: float, focal_dist: float):
        self.lens_radius = aperture / 2
        theta = vert_FOV * pi / 180
        half_height = tan(theta / 2)
        half_width = aspect_ratio * half_height

        self.w = (look_from - look_at).unit()
        self.u = Vec3.cross(up, self.w).unit()
        self.v = Vec3.cross(self.w, self.u)

        self.eye = look_from
        self.lower_left = self.eye - self.u * half_width * focal_dist - self.v * half_height * focal_dist - self.w * focal_dist
        self.horizontal = self.u * 2 * half_width * focal_dist
        self.vertical = self.v * 2 * half_height * focal_dist
Beispiel #6
0
    def scatter(self, r_in: Ray, hitPoint: Vec3, hitNormal: Vec3, \
                attenuation: Vec3, scattered: Ray):
        reflected = super().reflect(r_in.direction, hitNormal)
        attenuation.set(Vec3(1, 1, 1))
        if Vec3.dot(r_in.direction, hitNormal) > 0:
            outward_normal = hitNormal * -1
            ni_over_nt = self.reflective_index
            cosine = self.reflective_index * Vec3.dot(
                r_in.direction, hitNormal) / r_in.direction.length()
        else:
            outward_normal = hitNormal
            ni_over_nt = 1 / self.reflective_index
            cosine = -1 * Vec3.dot(r_in.direction,
                                   hitNormal) / r_in.direction.length()

        refracted = Vec3(0, 0, 0)
        if self.refract(r_in.direction, outward_normal, ni_over_nt, refracted):
            reflect_prob = self.schlick(cosine, self.reflective_index)
        else:
            reflect_prob = 1.0

        if random() < reflect_prob:
            scattered.set(Ray(hitPoint, reflected))
        else:
            scattered.set(Ray(hitPoint, refracted))

        return True
Beispiel #7
0
def lerp(pixels, cam, world):

    for x in range(RES_WIDTH):
        for y in range(RES_HEIGHT):
            col = Vec3(0.0, 0.0, 0.0)

            for _ in range(LERP_SAMPLE_DENSITY):
                u = float(x + random()) / RES_WIDTH
                v = float(y + random()) / RES_HEIGHT

                r = cam.get_ray(u, v)
                # p = r.point_at_param(2.0)
                col = col + color(r, world, 0)

            col = col / LERP_SAMPLE_DENSITY
            col = Vec3(col.x**0.5, col.y**0.5, col.z**0.5)
            ir = min(255, int(255.99 * col.x))
            ig = min(255, int(255.99 * col.y))
            ib = min(255, int(255.99 * col.z))
            pixels[x, RES_HEIGHT - 1 - y] = (ir, ig, ib)
Beispiel #8
0
    def hit(self, r: Ray, t_min: float, t_max: float, rec: HitRecord):
        oc = r.origin - self.center
        a = Vec3.dot(r.direction, r.direction)
        b = Vec3.dot(oc, r.direction)
        c = Vec3.dot(oc, oc) - (self.radius) * (self.radius)
        discriminant = b * b - a * c

        h0 = (-b - discriminant**(0.5)) / a
        h1 = (-b + discriminant**(0.5)) / a

        h = where((h0 > 0) & (h0 < h1), h0, h1)
        pred = (discriminant > 0) & (h > 0)

        if discriminant > 0:
            rec.t = where(pred, h, t_max)
            rec.hitPoint.set(r.point_at_param(rec.t))
            rec.normal.set((rec.hitPoint - self.center)) / self.radius
            rec.material = self.material
            return True
        else:
            return False
Beispiel #9
0
def color(r: Ray, world: Hitable, depth: int) -> Vec3:
    rec = HitRecord(0, Vec3(0, 0, 0), Vec3(0, 0, 1))

    if world.hit(r, 0.001, MAX_RAY_LENGTH, rec):
        attenuation = Vec3(0, 0, 0)
        scattered = Ray(Vec3(0, 0, 0), Vec3(1, 0, 0))
        if depth < 50 and \
            rec.material.scatter(r, rec.hitPoint, rec.normal, attenuation, scattered):
            return attenuation * color(scattered, world, depth + 1)
        else:
            return Vec3(0, 0, 0)

    else:
        unit_direction = r.direction.unit()
        t = 0.5 * (unit_direction.y + 1)
        return Vec3(1.0, 1.0, 1.0) * (1.0 - t) + Vec3(0.5, 0.7, 1.0) * t
Beispiel #10
0
 def scatter(self, r_in: Ray, hitPoint: Vec3, hitNormal: Vec3, \
     attenuation: Vec3, scattered: Ray):
     target = hitPoint + hitNormal + super().random_in_unit_sphere()
     scattered.set(Ray(hitPoint, target - hitPoint))
     attenuation.set(self.albedo)
     return True
Beispiel #11
0
 def reflect(v: Vec3, n: Vec3):
     return v - n * 2 * Vec3.dot(v, n)
Beispiel #12
0
def random_scene():
    hit_list = []
    hit_list.append(
        Sphere(Vec3(0, -1000, 0), 1000, Lambertian(Vec3(0.5, 0.5, 0.5))))
    for a in range(-11, 12):
        for b in range(-11, 12):
            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
                    hit_list.append(
                        Sphere(
                            center, 0.2,
                            Lambertian(
                                Vec3(random() * random(),
                                     random() * random(),
                                     random() * random()))))
                elif choose_mat < 0.95:  #metal
                    hit_list.append(
                        Sphere(
                            center, 0.2,
                            Specular(
                                Vec3(0.5 * (1 + random()),
                                     0.5 * (1 + random()),
                                     0.5 * (1 + random())), 0.5 * random())))
                else:  #glass
                    hit_list.append(Sphere(center, 0.2, Dielectric(1.5)))

    hit_list.append(Sphere(Vec3(0, 1, 0), 1.0, Dielectric(1.5)))
    hit_list.append(
        Sphere(Vec3(-4, 1, 0), 1.0, Lambertian(Vec3(0.4, 0.2, 0.1))))
    hit_list.append(
        Sphere(Vec3(4, 1, 0), 1.0, Specular(Vec3(0.7, 0.6, 0.5), 0.0)))

    return hit_list
Beispiel #13
0
                                     0.5 * (1 + random())), 0.5 * random())))
                else:  #glass
                    hit_list.append(Sphere(center, 0.2, Dielectric(1.5)))

    hit_list.append(Sphere(Vec3(0, 1, 0), 1.0, Dielectric(1.5)))
    hit_list.append(
        Sphere(Vec3(-4, 1, 0), 1.0, Lambertian(Vec3(0.4, 0.2, 0.1))))
    hit_list.append(
        Sphere(Vec3(4, 1, 0), 1.0, Specular(Vec3(0.7, 0.6, 0.5), 0.0)))

    return hit_list


if __name__ == '__main__':
    seed()
    look_from = Vec3(3, 3, 2)
    look_to = Vec3(0, 0, -1)
    dist_to_focus = (look_from - look_to).length()
    aperture = 2.0
    cam = Camera(look_from, look_to, Vec3(0, 1, 0), 90, RES_WIDTH / RES_HEIGHT,
                 aperture, dist_to_focus)
    # hit_list = []
    # hit_list.append(Sphere(Vec3(0,0,-1), 0.5, Lambertian(Vec3(0.1, 0.2, 0.5))))
    # hit_list.append(Sphere(Vec3(0,-100.5,-1), 100, Lambertian(Vec3(0.8, 0.8, 0))))
    # hit_list.append(Sphere(Vec3(1,0,-1), 0.5, Specular(Vec3(0.8, 0.6, 0.2))))
    # hit_list.append(Sphere(Vec3(-1,0,-1), 0.5, Dielectric(1.5)))
    # hit_list.append(Sphere(Vec3(-1,0,-1), -0.45, Dielectric(1.5)))
    hit_list = random_scene()
    world = HitableList(hit_list)

    # S is the screen coordinates (x0, y0, x1, y1)
Beispiel #14
0
 def random_in_unit_disk():
     while True:
         p = Vec3(random(), random(), 0) * 2.0 - Vec3(1, 1, 0)
         if Vec3.dot(p, p) >= 1.0:
             break
     return p