Esempio n. 1
0
def path_push(path: Path, ray: Ray):
    # update stuff appropriately
    if path.direction == Direction.STORAGE.value:
        # don't change anything, this is just a stack. this reduces wasted calculation and preserves first-vertex values
        pass
    elif path.ray is None:
        # this shouldn't come up
        pass
    else:
        G = geometry_term(path.ray, ray)
        path.ray.direction = unit(ray.origin - path.ray.origin)
        if path.ray.prev is None:
            # pushing onto stack of 1, just propagate p and color (?)
            ray.color = path.ray.color * G
            ray.p = path.ray.p * G
        else:
            # pushing onto stack of 2 or more, do some work
            brdf = BRDF_function(path.ray.material, -1 * path.ray.prev.direction, path.ray.normal, path.ray.direction,
                                       path.direction)
            ray.color = path.ray.local_color * path.ray.color * brdf * G
            ray.p = path.ray.p * G * BRDF_pdf(path.ray.material, -1 * path.ray.prev.direction, path.ray.normal, path.ray.direction,
                                          path.direction)
        ray.bounces = path.ray.bounces + 1

    # store new ray
    ray.prev = path.ray
    path.ray = ray
Esempio n. 2
0
def extend_path(path, root, path_direction):
    for i in range(MAX_BOUNCES):
        ray = path[-1]
        triangle, t = traverse_bvh(root, ray)
        if triangle is not None:
            # generate new ray
            #  new vectors
            origin = ray.origin + ray.direction * t
            direction = BRDF_sample(triangle.material, -1 * ray.direction,
                                    triangle.normal, path_direction)
            new_ray = Ray(origin, direction)

            #  store info from triangle
            new_ray.normal = triangle.normal
            new_ray.material = triangle.material
            new_ray.local_color = triangle.color
            if path_direction == Direction.FROM_CAMERA.value and triangle.emitter:
                new_ray.hit_light = True

            # probability, weight, and color updates
            G = geometry_term(ray, new_ray)

            if i == 0:
                # only need to multiply by G because p of this direction is already stored at creation
                new_ray.p = ray.p * G
                # same deal, "brdf" of source is already in ray.color
                new_ray.color = ray.color * G
                new_ray.G = G
            else:
                # so the idea here is that each vertex has information about everything up to it but not including it,
                # because we can't be sure of anything about the final bounce until we know the joining vertex
                bounce_p = BRDF_pdf(ray.material, -1 * path[-2].direction,
                                    ray.normal, ray.direction, path_direction)
                new_ray.p = ray.p * G * bounce_p
                new_ray.color = ray.color * ray.local_color * G * BRDF_function(
                    ray.material, -1 * path[-2].direction, ray.normal,
                    ray.direction, path_direction)
                new_ray.G = G
                ray.local_p = bounce_p

            path.append(new_ray)
        else:
            break
Esempio n. 3
0
def generate_light_ray(box: Box):
    light_index = np.random.randint(0, len(box.lights))
    light = box.lights[light_index]
    light_origin = light.sample_surface()
    x, y, z = local_orthonormal_system(light.normal)
    light_direction = random_hemisphere_uniform_weighted(x, y, z)
    ray = Ray(light_origin, light_direction)
    ray.color = light.color
    ray.local_color = light.color
    ray.normal = light.normal
    ray.p = 1 / (2 * np.pi * light.surface_area)
    return ray
Esempio n. 4
0
def path_push(path: Path, ray: Ray):
    # update stuff appropriately
    G = geometry_term(path.ray, ray)
    path.ray.direction = unit(ray.origin - path.ray.origin)
    if path.ray.prev is None:
        # pushing onto stack of 1, just propagate p and color (?)
        ray.color = path.ray.color * G
        ray.p = path.ray.p * G
    else:
        # pushing onto stack of 2 or more, do some work
        brdf = brdf_function(path.ray.material, -1 * path.ray.prev.direction,
                             path.ray.normal, path.ray.direction,
                             path.direction)
        ray.color = path.ray.local_color * path.ray.color * brdf * G
        ray.p = path.ray.p * G * brdf_pdf(
            path.ray.material, -1 * path.ray.prev.direction, path.ray.normal,
            path.ray.direction, path.direction)
    ray.bounces = path.ray.bounces + 1

    # store new ray
    ray.prev = path.ray
    path.ray = ray
Esempio n. 5
0
def generate_light_ray(emitters):

    light = emitters[np.random.randint(0, len(emitters))]
    light_origin = light.sample_surface()

    x, y, z = local_orthonormal_system(light.normal)
    light_direction = random_hemisphere_uniform_weighted(x, y, z)
    ray = Ray(light_origin, light_direction)

    ray.color = light.color
    ray.local_color = light.color
    ray.normal = light.normal

    # this seems made up
    ray.p = 1 / (2 * np.pi * light.surface_area)

    return ray