예제 #1
0
    def trace(self, origin, direction, depth=0):
        intersection = self._intersector.intersection(origin, direction)

        if depth >= self._options['max_depth'] or not intersection:
            # no intersection detected or we have reached max recursive depth for relfection or refraction
            if self._options['envmap']:
                return self._scene.envmap(origin, direction) 
            return Vector3(0.2, 0.7, 0.8)

        refraction = self._ray_refractor.calculate_refraction(origin, direction, intersection, depth)
        reflection = self._ray_reflector.calculate_reflection(origin, direction, intersection, depth)

        light_intensity, specular_light_intensity = self._light_tracer.calculate_intensity(origin, direction, intersection, depth)

        # resut vecotr - it's a material color
        result_vector = intersection.material.diffuse_color

        # apply light
        result_vector = result_vector * light_intensity * intersection.material.albedo[0]

        # add specular intensity
        result_vector += Vector3(1, 1, 1) * specular_light_intensity * intersection.material.albedo[1]
        
        # add reflection
        result_vector += reflection * intersection.material.albedo[2]

        # add refraction
        result_vector += refraction * intersection.material.albedo[3]

        return result_vector
예제 #2
0
    def calculate_reflection(self, origin, direction, intersection, depth):
        if not self._options['reflect']:
            return Vector3()

        reflect_dir = self._reflect(direction, intersection.normal).normalize()
        reflect_origin = utils.build_origin(intersection.point, reflect_dir, intersection.normal)

        return self._tracer.trace(reflect_origin, reflect_dir, depth + 1)
예제 #3
0
def cross(v1: Vector3, v2: Vector3) -> Vector3:
    x = v1._coordinates[1] * v2._coordinates[2] - v1._coordinates[
        2] * v2._coordinates[1]
    y = v1._coordinates[2] * v2._coordinates[0] - v1._coordinates[
        0] * v2._coordinates[2]
    z = v1._coordinates[0] * v2._coordinates[1] - v1._coordinates[
        1] * v2._coordinates[0]

    return Vector3(x, y, z)
예제 #4
0
    def envmap(self, origin, direction):
        width, height = self._envmap.width, self._envmap.height

        direction = direction.normalize()

        x = int((math.atan2(direction.z, direction.x) / (2 * math.pi) + 0.5) * width)
        y = int(math.acos(direction.y) / math.pi * height)

        r, g, b = self._envmap.getpixel((x, y))
        return Vector3(r / 255, g / 255, b / 255)
예제 #5
0
    def render(self, scene):
        start = time.time()
        frame = self._create_frame()
        total_count = self._width * self._height
        proceesed_count = 0
        percent = 0

        ray_tracer = RayTracer(scene, self._options)

        print('RENDERING: [', end='', flush=True)
        for j in range(self._height):
            y = -(2 *
                  (j + 0.5) / self._height - 1) * math.tan(self._fov_hor / 2)

            for i in range(self._width):
                x = (2 * (i + 0.5) / self._width - 1) * math.tan(
                    self._fov_vert / 2)

                origin = Vector3(0, 0, 0)
                direction = Vector3(x, y, -1).normalize()

                vector = ray_tracer.trace(origin, direction)

                frame[i +
                      j * self._width] = self._cast_vector_to_rgb_tuple(vector)
                proceesed_count += 1

            if ((proceesed_count / total_count) * 100) // 10 > percent:
                percent += 1
                print('#', end='', flush=True)

        print(']')

        print('[RENDER FINISHED options=%s] took: %.2f sec.' %
              (self._options, time.time() - start))
        return Frame(self._width, self._height, frame)
예제 #6
0
def refract(v, normal, refractive_index):
    cos_v = -max(-1.0, min(1.0, v * normal))
    etav, etat = 1, refractive_index

    if cos_v < 0:
        cos_v = -cos_v
        etav, etat = etat, etav
        normal = -normal

    eta = etav / etat
    k = 1 - eta * eta * (1 - cos_v**2)

    if k < 0:
        res_vector = Vector3(1, 0, 0)
    else:
        res_vector = v * eta + normal * (eta * cos_v - math.sqrt(k))

    return res_vector