Ejemplo n.º 1
0
    def scatter(self, ray_in: Ray, hit_record: hit_record):
        outward_normal = Vector3(1, 1, 1)
        reflected = ray_in.direction().reflect(hit_record.normal)
        ni_over_nt = 0
        attenuation = Vector3(1, 1, 1)
        scattered = Vector3(0, 0, 0)
        reflect_prob = 0
        cosine = 0

        if (ray_in.direction().dot(hit_record.normal) > 0):
            outward_normal = Vector3(0, 0, 0) - hit_record.normal
            ni_over_nt = self.ref_idx
            cosine = self.ref_idx * ray_in.direction().dot(
                hit_record.normal) / ray_in.direction().length()
        else:
            outward_normal = hit_record.normal
            ni_over_nt = 1 / self.ref_idx
            cosine = -ray_in.direction().dot(
                hit_record.normal) / ray_in.direction().length()

        is_scattered, refracted = refract(ray_in.direction(), outward_normal,
                                          ni_over_nt)
        if (is_scattered):
            reflect_prob = schlick(cosine, self.ref_idx)
        else:
            scattered = Ray(hit_record.p, reflected)
            reflect_prob = 1.0

        if (random.uniform(0, 1) < reflect_prob):
            scattered = Ray(hit_record.p, reflected)
        else:
            scattered = Ray(hit_record.p, refracted)

        return (True, scattered, attenuation)
Ejemplo n.º 2
0
    def scatter(self, r_in: Ray, hit_rec):

        if r_in.direction.dot(hit_rec.normal) > 0:
            outward_normal = -hit_rec.normal
            n1_n2 = self.ref_idx
            cosine = self.ref_idx * r_in.direction.dot(
                hit_rec.normal) / r_in.direction.norm()
        else:
            outward_normal = hit_rec.normal
            n1_n2 = self.inv_ref_idx
            cosine = -r_in.direction.dot(
                hit_rec.normal) / r_in.direction.norm()

        ret_val, refracted = refract(r_in.direction, outward_normal, n1_n2)
        if ret_val:
            reflect_prob = schlick(cosine, self.ref_idx)
        else:
            reflect_prob = 1.0

        if random.random() < reflect_prob:
            reflected = reflect(unit_vector(r_in.direction), hit_rec.normal)
            scattered_ray = Ray(hit_rec.p, reflected)
        else:
            scattered_ray = Ray(hit_rec.p, refracted)

        return True, scattered_ray, self.attenuation
Ejemplo n.º 3
0
    def scatter(self, ray, rec, srec):
        srec.is_specular = True
        srec.pdf_ptr = 0
        srec.attenuation = Vec3(1.0, 1.0, 1.0)
        outward_normal = Vec3()
        reflected = ray.dir.reflect(rec.normal)
        refracted = Vec3()

        if ray.dir.dot(rec.normal) > 0:
            outward_normal = -rec.normal
            ni_over_nt = self.ref_idx
            cosine = self.ref_idx * ray.dir.dot(rec.normal) / ray.dir.length()
        else:
            outward_normal = rec.normal
            ni_over_nt = 1.0 / self.ref_idx
            cosine = -ray.dir.dot(rec.normal) / ray.dir.length()

        if self.refract(ray.dir, outward_normal, ni_over_nt, refracted):
            reflect_prob = self.schlick(cosine, self.ref_idx)
        else:
            reflect_prob = 1.0

        if random() < reflect_prob:
            srec.specular_ray = Ray(rec.p, reflected)
        else:
            srec.specular_ray = Ray(rec.p, refracted)
        return True
Ejemplo n.º 4
0
    def testTransformation(self):
        plane = Plane(transformation=rotation_y(angle_deg=90.0))

        ray1 = Ray(origin=Point(1, 0, 0), dir=-VEC_X)
        intersection1 = plane.ray_intersection(ray1)
        assert intersection1
        assert HitRecord(
            world_point=Point(0.0, 0.0, 0.0),
            normal=Normal(1.0, 0.0, 0.0),
            surface_point=Vec2d(0.0, 0.0),
            t=1.0,
            ray=ray1,
            material=plane.material,
        ).is_close(intersection1)

        ray2 = Ray(origin=Point(0, 0, 1), dir=VEC_Z)
        intersection2 = plane.ray_intersection(ray2)
        assert not intersection2

        ray3 = Ray(origin=Point(0, 0, 1), dir=VEC_X)
        intersection3 = plane.ray_intersection(ray3)
        assert not intersection3

        ray4 = Ray(origin=Point(0, 0, 1), dir=VEC_Y)
        intersection4 = plane.ray_intersection(ray4)
        assert not intersection4
Ejemplo n.º 5
0
def getColor(ray, depth):
    result = np.array([0, 0, 0], float)
    if depth == 0:
        return result

    hit = getClose(ray)
    if hit is None:
        return result

    # Phong
    for l in lights:
        p = hit.p + hit.n / 1000
        if getShadow(Ray(p, l.pos - p)):
            continue
        lm = (l.pos - hit.p).normalized()
        kl = lm.dot(hit.n)
        if kl > 0:
            result += kl * hit.m.d * l.m.d * hit.c
        kv = -ray.v.dot(2 * kl * hit.n - lm)
        if kv > 0:
            result += (kv**hit.m.sh) * hit.m.s * l.m.s
    result += ia * hit.m.a * hit.c
    if hit.m.r > 0:
        reflect = -2 * ray.v.dot(hit.n) * hit.n + ray.v
        result += hit.m.r * getColor(Ray(hit.p + hit.n / 1000, reflect),
                                     depth - 1)
    return result
    def scatter(self, r_in, rec):
        outward_normal = Vec3()
        reflected = Vec3.reflect(r_in.direction, rec["normal"])
        ni_over_nt = 0.0
        attenuation = Vec3(1.0, 1.0, 1.0)
        cosine = 0.0
        if Vec3.dot(r_in.direction, rec["normal"]) > 0:
            outward_normal = -rec["normal"]
            ni_over_nt = self.ref_idx
            cosine = self.ref_idx * Vec3.dot(
                r_in.direction, rec["normal"]) / r_in.direction.length()
        else:
            outward_normal = rec["normal"]
            ni_over_nt = 1.0 / self.ref_idx
            cosine = -Vec3.dot(r_in.direction,
                               rec["normal"]) / r_in.direction.length()

        scattered = Ray()
        reflect_prob = 0.0
        refracted = Vec3.refract(r_in.direction, outward_normal, ni_over_nt)
        if refracted is not None:
            reflect_prob = schlick(cosine, self.ref_idx)
        else:
            reflect_prob = 1.0
        if random() < reflect_prob:
            scattered = Ray(rec["p"], reflected)
        else:
            scattered = Ray(rec["p"], refracted)
        return attenuation, scattered
Ejemplo n.º 7
0
    def trace_non_diffuse(self, ray, scene):
        self.__scene = scene
        hit_object, hit_point, hit_normal = self.__intersect(ray)

        traced_color = Vector3()
        reflection_ray = Ray(Vector3(), Vector3(), 0)
        refraction_ray = Ray(Vector3(), Vector3(), 0)
        fresnel = 0

        if hit_object is None:
            return reflection_ray, refraction_ray, fresnel

        if not hit_object.material.is_diffuse:
            inside = ray.direction.dot(hit_normal) > 0
            if inside:
                hit_normal = -hit_normal
            facing_ratio = -ray.direction.dot(hit_normal)
            fresnel = self.__mix((1 - facing_ratio)**2, 1, 0.1)
            reflection_ray = Ray(hit_point + self.__bias * hit_normal,
                                 ray.direction.reflect(hit_normal).normalize())

            refraction = Vector3()

            # transparent?
            if hit_object.material.transparency > 0:
                from_ior = ray.current_ior if inside else hit_object.material.ior
                to_ior = hit_object.material.ior if inside else ray.current_ior
                refraction_ray = Ray(
                    hit_point - self.__bias * hit_normal,
                    ray.direction.refract(from_ior, to_ior,
                                          hit_normal).normalize())

        # mix according to fresnel
        return reflection_ray, refraction_ray, fresnel
Ejemplo n.º 8
0
    def __trace_non_diffuse(self, ray, hit_object, hit_point, hit_normal,
                            depth):
        """Traces color of an object with refractive/reflective material"""
        inside = ray.direction.dot(hit_normal) > 0
        if inside:
            hit_normal = -hit_normal
        # corret the normal vector in case it points inside of the sphere

        facing_ratio = -ray.direction.dot(hit_normal)
        fresnel = self.__mix((1 - facing_ratio)**2, 1, 0.1)
        reflection_ray = Ray(hit_point + self.__bias * hit_normal,
                             ray.direction.reflect(hit_normal).normalize())
        reflection = self.__trace_recursively(reflection_ray, depth + 1)

        refraction = Vector3()

        # transparent?
        if hit_object.material.transparency > 0:
            from_ior = ray.current_ior if inside else hit_object.material.ior
            to_ior = hit_object.material.ior if inside else ray.current_ior
            refraction_ray = Ray(
                hit_point - self.__bias * hit_normal,
                ray.direction.refract(from_ior, to_ior,
                                      hit_normal).normalize())
            refraction = self.__trace_recursively(refraction_ray, depth + 1)

        # mix according to fresnel
        return ((reflection * fresnel + refraction *
                 (1 - fresnel) * hit_object.material.transparency).mul_comp(
                     hit_object.material.surface_color))
Ejemplo n.º 9
0
def shadow_ray_pass(ray, rng, indirectPass=False):
    r = ray
    L = Vector3()
    F = Vector3(1.0, 1.0, 1.0)

    while True:
        hit, id = intersect(r)
        if (not hit):
            return L

        shape = spheres[id]
        p = r(r.tmax)
        n = (p - shape.p).normalize()

        if indirectPass:
            if shape.reflection_t == Sphere.Reflection_t.DIFFUSE:
                F *= (shape.f / math.pi)
            else:
                F *= shape.f

        if shape.name == "light":
            return shape.e

        # Bounce another ray if the surface is reflective or refractive
        if shape.reflection_t == Sphere.Reflection_t.SPECULAR:
            d = ideal_specular_reflect(r.d, n)
            r = Ray(p, d, tmin=Sphere.EPSILON, depth=r.depth + 1)
            continue
        elif shape.reflection_t == Sphere.Reflection_t.REFRACTIVE:
            d, pr = ideal_specular_transmit(r.d, n, REFRACTIVE_INDEX_OUT,
                                            REFRACTIVE_INDEX_IN, rng)
            F *= pr
            r = Ray(p, d, tmin=Sphere.EPSILON, depth=r.depth + 1)
            continue

        light_list = lights()
        for light in light_list:
            #get the spherical angle of the light projected from the point on the surface
            light_vec = light.p - p
            cos_projected_angle = math.sqrt(1 - (pow(light.r, 2) /
                                                 light_vec.norm2_squared()))
            projected_angle = math.acos(cos_projected_angle)
            shadow_ray_dir = unit_hemisphere_vector(
                light_vec,
                rng.uniform_float() * projected_angle,
                rng.uniform_range_float(0, 2 * math.pi))
            shadow_ray_vec = Ray(p,
                                 shadow_ray_dir,
                                 tmin=Sphere.EPSILON,
                                 depth=r.depth + 1)
            inv_shadow_ray_pdf = 2 * math.pi * (1 - cos_projected_angle)

            hit, id = intersect(shadow_ray_vec)
            if spheres[id] != light:
                continue
            else:
                cos_incident_angle_surface = shadow_ray_vec.d.dot(n)
                L += F * light.e * cos_incident_angle_surface * inv_shadow_ray_pdf * math.pi

        return L
Ejemplo n.º 10
0
    def scatter(self, ray, hitrec):
        reflected = reflect(ray.direction, hitrec.normal)
        if (np.dot(ray.direction, hitrec.normal) > 0.0):
            outward_normal = -hitrec.normal
            ni_over_nt = self.ref_idx
            cosine = self.ref_idx * np.dot(ray.direction, hitrec.normal) / (
                math.sqrt(np.sum(ray.direction * ray.direction)))
        else:
            outward_normal = hitrec.normal
            ni_over_nt = 1.0 / self.ref_idx
            cosine = -np.dot(ray.direction, hitrec.normal) / (math.sqrt(
                np.sum(ray.direction * ray.direction)))

        is_refract, refracted = refract(ray.direction, outward_normal,
                                        ni_over_nt)
        if (is_refract):
            reflect_prob = schlick(cosine, self.ref_idx)
        else:
            reflect_prob = 1.0
        if (random.uniform(0.0, 1.0) < reflect_prob):
            scattered = Ray(hitrec.p, reflected)
        else:
            scattered = Ray(hitrec.p, refracted)

        return True, scattered, np.array([1.0, 1.0, 1.0])
Ejemplo n.º 11
0
    def scatter(self, ray_in, rec):
        attenuation = Vec3(1.0, 1.0, 1.0)
        if rec.frontFacing:
            etai_over_etat = 1 / self.refractive_index
        else:
            etai_over_etat = self.refractive_index

        unit_direction = ray_in.direction.norm()

        cos_theta = min(dot(rec.normal, -unit_direction), 1.0)
        sin_theta = math.sqrt(1.0 - cos_theta * cos_theta)

        if etai_over_etat * sin_theta > 1.0:
            reflected = reflect(unit_direction, rec.normal)
            scattered = Ray(rec.position, reflected)
            return True, scattered, attenuation

        reflection_probability = schlick(cos_theta, etai_over_etat)
        if random.random() < reflection_probability:
            reflected = reflect(unit_direction, rec.normal)
            scattered = Ray(rec.position, reflected)
            return True, scattered, attenuation

        refracted = refract(unit_direction, rec.normal, etai_over_etat)
        scattered = Ray(rec.position, refracted)
        return True, scattered, attenuation
Ejemplo n.º 12
0
def albedo_pass(ray, rng):
    r = ray
    L = Vector3()
    F = Vector3(1.0, 1.0, 1.0)

    while True:
        hit, id = intersect(r)
        if (not hit):
            return L

        shape = spheres[id]
        p = r(r.tmax)
        n = (p - shape.p).normalize()

        if shape.reflection_t == Sphere.Reflection_t.DIFFUSE:
            F *= (shape.f / math.pi)
        else:
            F *= shape.f

        if shape.reflection_t == Sphere.Reflection_t.SPECULAR:
            d = ideal_specular_reflect(r.d, n)
            r = Ray(p, d, tmin=Sphere.EPSILON, depth=r.depth + 1)
            continue
        elif shape.reflection_t == Sphere.Reflection_t.REFRACTIVE:
            d, pr = ideal_specular_transmit(r.d, n, REFRACTIVE_INDEX_OUT,
                                            REFRACTIVE_INDEX_IN, rng)
            F *= pr
            r = Ray(p, d, tmin=Sphere.EPSILON, depth=r.depth + 1)
            continue
        elif shape.name == "light":
            L = shape.e
            return L
        else:
            L = F
            return L
Ejemplo n.º 13
0
    def scatter(self, r_in: Ray, rec: hit_record):
        reflected: np.ndarray = reflect(r_in.direction(), rec.normal)
        attenuation = np.array((1, 1, 1), float)
        if np.dot(r_in.direction(), rec.normal) > 0:
            outward_normal = -rec.normal
            ni_over_nt = self.ref_idx
            cosine = self.ref_idx * np.dot(r_in.direction(),
                                           rec.normal) / np.linalg.norm(
                                               r_in.direction())

        else:
            outward_normal = rec.normal
            ni_over_nt = 1.0 / self.ref_idx
            cosine = float(-np.dot(r_in.direction(), rec.normal) /
                           np.linalg.norm(r_in.direction()))

        has_refracted, refracted = refract(r_in.direction(), outward_normal,
                                           ni_over_nt)
        if has_refracted:
            reflect_prob = schlick(cosine, self.ref_idx)

        else:
            reflect_prob = 1

        if random() < reflect_prob:
            scattered = Ray(rec.p, reflected, r_in.time())

        else:
            scattered = Ray(rec.p, refracted, r_in.time())

        return True, attenuation, scattered
Ejemplo n.º 14
0
    def testTransformation(self):
        sphere = Sphere(transformation=translation(Vec(10.0, 0.0, 0.0)))

        ray1 = Ray(origin=Point(10, 0, 2), dir=-VEC_Z)
        intersection1 = sphere.ray_intersection(ray1)
        assert intersection1
        assert HitRecord(
            world_point=Point(10.0, 0.0, 1.0),
            normal=Normal(0.0, 0.0, 1.0),
            surface_point=Vec2d(0.0, 0.0),
            t=1.0,
            ray=ray1,
            material=sphere.material,
        ).is_close(intersection1)

        ray2 = Ray(origin=Point(13, 0, 0), dir=-VEC_X)
        intersection2 = sphere.ray_intersection(ray2)
        assert intersection2
        assert HitRecord(
            world_point=Point(11.0, 0.0, 0.0),
            normal=Normal(1.0, 0.0, 0.0),
            surface_point=Vec2d(0.0, 0.5),
            t=2.0,
            ray=ray2,
            material=sphere.material,
        ).is_close(intersection2)

        # Check if the sphere failed to move by trying to hit the untransformed shape
        assert not sphere.ray_intersection(
            Ray(origin=Point(0, 0, 2), dir=-VEC_Z))

        # Check if the *inverse* transformation was wrongly applied
        assert not sphere.ray_intersection(
            Ray(origin=Point(-10, 0, 0), dir=-VEC_Z))
Ejemplo n.º 15
0
    def testHit(self):
        sphere = Sphere()

        ray1 = Ray(origin=Point(0, 0, 2), dir=-VEC_Z)
        intersection1 = sphere.ray_intersection(ray1)
        assert intersection1
        assert HitRecord(
            world_point=Point(0.0, 0.0, 1.0),
            normal=Normal(0.0, 0.0, 1.0),
            surface_point=Vec2d(0.0, 0.0),
            t=1.0,
            ray=ray1,
            material=sphere.material,
        ).is_close(intersection1)

        ray2 = Ray(origin=Point(3, 0, 0), dir=-VEC_X)
        intersection2 = sphere.ray_intersection(ray2)
        assert intersection2
        assert HitRecord(
            world_point=Point(1.0, 0.0, 0.0),
            normal=Normal(1.0, 0.0, 0.0),
            surface_point=Vec2d(0.0, 0.5),
            t=2.0,
            ray=ray2,
            material=sphere.material,
        ).is_close(intersection2)

        assert not sphere.ray_intersection(
            Ray(origin=Point(0, 10, 2), dir=-VEC_Z))
Ejemplo n.º 16
0
    def test_is_close(self):
        ray1 = Ray(origin=Point(1.0, 2.0, 3.0), dir=Vec(5.0, 4.0, -1.0))
        ray2 = Ray(origin=Point(1.0, 2.0, 3.0), dir=Vec(5.0, 4.0, -1.0))
        ray3 = Ray(origin=Point(5.0, 1.0, 4.0), dir=Vec(3.0, 9.0, 4.0))

        assert ray1.is_close(ray2)
        assert not ray1.is_close(ray3)
Ejemplo n.º 17
0
def to_3d_point(p1, p2):
    x1 = p1[0]
    y1 = p1[1]
    x2 = p2[0]
    y2 = p2[1]
    u1 = c1toGlobal.dot([(x1 - cx) / fx, (y1 - cy) / fy, 1, 0])[0:3]
    u2 = c2toGlobal.dot([(x2 - cx) / fx, (y2 - cy) / fy, 1, 0])[0:3]
    ray1 = Ray(c1Pos, u1)
    ray2 = Ray(c2Pos, u2)
    return ray1.find_closest_point(ray2)
 def test_ray_misses_cylinder(self):
     cyl = Cylinder()
     rays = [
         Ray(Point(1, 0, 0), Vector(0, 1, 0)),
         Ray(Point(0, 0, 0), Vector(0, 1, 0)),
         Ray(Point(0, 0, -5), Vector(1, 1, 1))
     ]
     for ray in rays:
         direction = Vector.normalize(ray.direction)
         r = Ray(ray.origin, direction)
         xs = cyl.local_intersect(r)
         self.assertEqual(len(xs), 0)
Ejemplo n.º 19
0
    def testUVCoordinates(self):
        plane = Plane()

        ray1 = Ray(origin=Point(0, 0, 1), dir=-VEC_Z)
        intersection1 = plane.ray_intersection(ray1)
        assert intersection1.surface_point.is_close(Vec2d(0.0, 0.0))

        ray2 = Ray(origin=Point(0.25, 0.75, 1), dir=-VEC_Z)
        intersection2 = plane.ray_intersection(ray2)
        assert intersection2.surface_point.is_close(Vec2d(0.25, 0.75))

        ray3 = Ray(origin=Point(4.25, 7.75, 1), dir=-VEC_Z)
        intersection3 = plane.ray_intersection(ray3)
        assert intersection3.surface_point.is_close(Vec2d(0.25, 0.75))
Ejemplo n.º 20
0
    def scatter(self, r_in, p, n):
        v = r_in.direction()
        if v.dot(n) > 0:
            outward_normal = -n
            refrac_ratio = self.refrac_index
        else:
            outward_normal = n
            refrac_ratio = 1 / self.refrac_index

        v_refrac = refract(v, outward_normal, refrac_ratio)
        if v_refrac:
            return Ray(p, v_refrac), Vec3(1, 1, 1)
        else:
            return Ray(p, reflect(v, n)), Vec3(1, 1, 1)
Ejemplo n.º 21
0
 def test_intersect3(self):
     origin = Point(0, 2, -5)
     direction = Vector(0, 0, 1)
     r = Ray(origin, direction)
     s = Sphere()
     xs = Intersections([])
     self.assertTrue(s.intersect(r) == xs)
Ejemplo n.º 22
0
def ray_color(ray, background, world, lights, depth):
    '''Determine the color of a ray based on the objects in a scene (recursive with a max depth)'''
    rec = HitRecord()

    # Don't exceed ray bounce limit
    if depth <= 0:
        return Vec3(0, 0, 0)

    # If the ray hits nothing, return background color
    if not world.hit(ray, 0.001, float('inf'), rec):
        return background

    # Determine if the object emits light or has a specular material
    srec = ScatterRecord()
    emitted = rec.mat.emitted(ray, rec, rec.u, rec.v, rec.p)
    if not rec.mat.scatter(ray, rec, srec):
        return emitted
    if srec.is_specular:
        return srec.attenuation * ray_color(srec.specular_ray, background,
                                            world, lights, depth - 1)

    # Use PDFs to determine the next ray and call ray_color() again
    light_ptr = HittablePDF(lights, rec.p)
    p = MixturePDF(light_ptr, srec.pdf_ptr)
    scattered = Ray(rec.p, p.generate(), ray.time)
    pdf_val = p.value(scattered.dir)
    del srec.pdf_ptr

    return emitted + srec.attenuation * rec.mat.scattering_pdf(
        ray, rec, scattered) * ray_color(scattered, background, world, lights,
                                         depth - 1) / pdf_val
Ejemplo n.º 23
0
 def test_ray_originate_inside_sphere(self):
     r = Ray(Point(0, 0, 0), Vector(0, 0, 1))
     s = Sphere()
     xs = s.intersect(r)
     self.assertEqual(len(xs), 2)
     self.assertEqual(xs[0].t, -1.0)
     self.assertEqual(xs[1].t, 1.0)
Ejemplo n.º 24
0
 def test_sphere_behind_ray(self):
     r = Ray(Point(0, 0, 5), Vector(0, 0, 1))
     s = Sphere()
     xs = s.intersect(r)
     self.assertEqual(len(xs), 2)
     self.assertEqual(xs[0].t, -6.0)
     self.assertEqual(xs[1].t, -4.0)
Ejemplo n.º 25
0
def hard_shadow(ph, objects, l, dist_l):
    """
    Determines if this point should have a shadow for the light in pl.

    Args:
        ph: 3D Point of hit
        objects([Object]): list of objects that can be between the point and
            the light
        l(numpy.array): unit vector pointing to the light
        dist_l(float): distance to the light

    Returns:
        numpy.array: The calculated color for this hard shadow (RGB)
    """
    # Case outside of cone in SpotLight
    if np.array_equal(l, np.zeros(3)):
        return np.zeros(3)
    shadow_coef = 0
    r = Ray(ph, l)
    for obj in objects:
        # Cast ray from ph to the object with n = l and shadow if t < dist_l
        t = r.intersect(obj)
        if 0 < t < dist_l:
            shadow_coef = 1
            break
    shadow_color = np.zeros(3)
    # Use SHADOW_STRENGTH = 0 for no shadows and 1 for hard shadows
    shadow_coef *= max(0.0, min(SHADOW_STRENGTH, 1.0))
    color = COLOR_FOR_LIGHT * (1 - shadow_coef) + shadow_color * shadow_coef
    return color
Ejemplo n.º 26
0
    def ray_trace(self, ray, scene, depth=0):
        color = Color(0, 0, 0)
        #Find the nearest object hited by the ray in the scene
        dist_hit, obj_hit = self.find_nearest(ray, scene)
        if obj_hit is None:
            return color
        hit_pos = ray.origin + ray.direction * dist_hit
        #We calculate the normal at the hit position
        hit_normal = obj_hit.normal(hit_pos)
        color += self.color_at(obj_hit, hit_pos, hit_normal, scene)
        """
            Making the reflections of the objects
            Finding the reflected rays
            In order to make the algorithm more effient
            We use Monte Carlo for this
        """
        if probability():
            if depth < self.MAX_DEPTH:
                new_ray_pos = hit_pos + hit_normal * self.MIN_DISPLACE
                new_ray_dir = ray.direction - 2 * ray.direction.dot_product(
                    hit_normal) * hit_normal
                new_ray = Ray(new_ray_pos, new_ray_dir)
                # Attenuate the reflected ray by the reflection coefficient
                # calls the funtion of ray tracing again
                color += self.ray_trace(
                    new_ray, scene, depth + 1) * obj_hit.material.reflection

        return color
Ejemplo n.º 27
0
 def test_intersect(self):
     r = Ray(Point(0, 0, -5), Vector(0, 0, 1))
     s = Sphere()
     xs = s.intersect(r)
     self.assertEqual(len(xs), 2)
     self.assertEqual(xs[0].object, s)
     self.assertEqual(xs[1].object, s)
Ejemplo n.º 28
0
    def test_intersect_with_transform(self):
        # intersect a scaled sphere
        r = Ray(Point(0, 0, -5), Vector(0, 0, 1))
        s = Sphere()
        s.transform = Matrix.scale(2, 2, 2)
        xs = s.intersect(r)
        self.assertEqual(len(xs), 2)
        self.assertEqual(xs[0].t, 3)
        self.assertEqual(xs[1].t, 7)

        # intersect a translated sphere
        r = Ray(Point(0, 0, -5), Vector(0, 0, 1))
        s = Sphere()
        s.transform = Matrix.translate(5, 0, 0)
        xs = s.intersect(r)
        self.assertEqual(len(xs), 0)
Ejemplo n.º 29
0
 def test_group_hit_bounding_box(self):
     child = Shape.test_shape()
     shape = Group()
     shape.add_child(child)
     r = Ray(Point(0, 0, -5), Vector(0, 0, 1))
     xs = shape.intersect(r)
     self.assertIsNotNone(child.saved_ray)
Ejemplo n.º 30
0
    def render(self, scene, hmin, hmax, part_file, rows_done):
        width = scene.width
        height = scene.height
        aspect_ratio = float(width) / height
        x0 = -1.0
        x1 = +1.0
        xstep = (x1 - x0) / (width - 1)
        y0 = -1.0 / aspect_ratio
        y1 = +1.0 / aspect_ratio
        ystep = (y1 - y0) / (height - 1)

        camera = scene.camera
        pixels = Image(width, hmax - hmin)

        for j in range(hmin, hmax):
            y = y0 + j * ystep
            for i in range(width):
                x = x0 + i * xstep
                ray = Ray(camera, Point(x, y) - camera)
                pixels.set_pixel(i, j - hmin, self.ray_trace(ray, scene))
            # Update progress bar
            if rows_done:
                with rows_done.get_lock():
                    rows_done.value += 1
                    print(
                        "{:3.0f}%".format(float(rows_done.value) / float(height) * 100),
                        end="\r",
                    )
        with open(part_file, "w") as part_fileobj:
            pixels.write_ppm_raw(part_fileobj)