Пример #1
0
    def scatter(self, ray, hit_record):
        reflected = reflect(ray.direction, hit_record.normal)

        # If the ray is inside the sphere set values accordingly
        if np.dot(ray.direction, hit_record.normal) > 0.:
            outward_normal = -hit_record.normal
            ni_over_nt = self.refraction_index
            cosine = self.refraction_index * np.dot(
                ray.direction, hit_record.normal) / length(ray.direction)
        else:
            outward_normal = hit_record.normal
            ni_over_nt = 1. / self.refraction_index
            cosine = -np.dot(ray.direction, hit_record.normal) / length(
                ray.direction)

        is_refracted, refracted = refract(ray.direction, outward_normal,
                                          ni_over_nt)

        # get probability of reflection over refraction with schlick approximation
        reflect_prob = self._schlick(cosine) if is_refracted else 1

        # set the scattered ray as either the reflection or refraction according to reflect_prob
        if random.random() < reflect_prob:
            self.scattered = Ray(hit_record.point, reflected, ray.time)
        else:
            self.scattered = Ray(hit_record.point, refracted, ray.time)

        return True
Пример #2
0
    def is_shadowed(self, light_position, hit_point):
        vec = subtract(light_position, hit_point)
        distance = magnitude(vec)
        direction = normalize(vec)

        ray = Ray(hit_point, direction)
        intersections = self.intersect(ray)
        hit_intersection = shadow_hit(intersections)
        return hit_intersection is not None and hit_intersection.t < distance
Пример #3
0
    def reflected_color(self, hit, remaining=5):
        if remaining <= 0:
            return color(0, 0, 0)

        if hit.object.material.reflective == 0.0:
            return color(0, 0, 0)

        reflect_ray = Ray(hit.over_point, hit.reflectv)
        reflect_color = self.color_at(reflect_ray, remaining - 1)
        return multiply(reflect_color, hit.object.material.reflective)
def main():
    canvas_pixels = 500
    canvas = Canvas(canvas_pixels, canvas_pixels)
    shape = Sphere()

    # assign material
    shape.material = Material()
    shape.material.color = color(1, 0.2, 1)

    light_position = point(-10, 10, -10)
    light_color = color(1, 1, 1)
    light = PointLight(light_position, light_color)

    ray_origin = point(0, 0, -5)
    wall_z = 10
    wall_size = 7.0

    pixel_size = wall_size / canvas_pixels
    half = wall_size / 2

    for y in range(canvas_pixels):
        world_y = half - pixel_size * y

        for x in range(canvas_pixels):
            world_x = -half + pixel_size * x

            pos = point(world_x, world_y, wall_z)

            r = Ray(ray_origin, normalize(subtract(pos, ray_origin)))
            xs = shape.intersect(r)

            shape_hit = hit(xs)
            if shape_hit is not None:
                hit_point = r.position_at(shape_hit.t)
                normal = shape_hit.object.normal_at(hit_point)
                eye = negate(r.direction)
                px_color = lighting(shape_hit.object.material,
                                    shape_hit.object, light, hit_point, eye,
                                    normal)
                canvas.set_pixel(x, y, px_color)

    with open('render_phong_sphere.ppm', 'w') as out_file:
        out_file.write(canvas.to_ppm())
Пример #5
0
    def ray_for_pixel(self, pixel_x, pixel_y):
        xoffset = (pixel_x + 0.5) * self.pixel_size
        yoffset = (pixel_y + 0.5) * self.pixel_size

        world_x = self.half_width - xoffset
        world_y = self.half_height - yoffset

        pixel = multiply_tuple(self.__inverse_transform,
                               point(world_x, world_y, -1))
        origin = multiply_tuple(self.__inverse_transform, point(0, 0, 0))
        direction = normalize(subtract(pixel, origin))

        return Ray(origin, direction)
Пример #6
0
def main():
    canvas_pixels = 400
    canvas = Canvas(canvas_pixels, canvas_pixels)
    red = color(1, 0, 0)
    shape = Sphere()

    # shrink it along the y axis
    #shape.set_transform(scaling(1, 0.5, 1))
    # shrink it along the x axis
    #shape.set_transform(scaling(0.5, 1, 1))
    # shrink it, and rotate it!
    # shape.set_transform(multiply_matrix(rotation_z(pi / 4), scaling(0.5, 1,
    #                                                                 1)))
    # shrink it, and skew it!
    # shape.set_transform(
    #     multiply_matrix(shearing(1, 0, 0, 0, 0, 0), scaling(0.5, 1, 1)))

    ray_origin = point(0, 0, -5)
    wall_z = 10
    wall_size = 7.0

    pixel_size = wall_size / canvas_pixels
    half = wall_size / 2

    for y in range(canvas_pixels):
        world_y = half - pixel_size * y

        for x in range(canvas_pixels):
            world_x = -half + pixel_size * x

            pos = point(world_x, world_y, wall_z)

            r = Ray(ray_origin, normalize(subtract(pos, ray_origin)))
            xs = shape.intersect(r)

            if hit(xs) is not None:
                canvas.set_pixel(x, y, red)

    with open('render_sphere.ppm', 'w') as out_file:
        out_file.write(canvas.to_ppm())
Пример #7
0
    def refracted_color(self, hit, remaining=5):
        if remaining <= 0:
            return color(0, 0, 0)

        if hit.object.material.transparency == 0.0:
            return color(0, 0, 0)

        n_ratio = hit.n1 / hit.n2
        cos_i = dot(hit.eyev, hit.normalv)
        sin2_t = n_ratio**2 * (1 - cos_i**2)

        if sin2_t > 1.0:
            return color(0, 0, 0)

        cos_t = sqrt(1.0 - sin2_t)

        direction = subtract(multiply(hit.normalv, (n_ratio * cos_i - cos_t)),
                             multiply(hit.eyev, n_ratio))

        refract_ray = Ray(hit.under_point, direction)

        return multiply(self.color_at(refract_ray, remaining - 1),
                        hit.object.material.transparency)
Пример #8
0
def step_impl(context):
    context.r = Ray(context.origin, context.direction)
Пример #9
0
def step_create_ray_with_specific_point_and_direction(context, dx, dy, dz):
    context.r = Ray(point(0, 0, sqrt(2) / 2), vector(dx, dy, dz))
Пример #10
0
def step_create_ray_with_point_and_specific_direction(context, ox, oy, oz):
    context.r = Ray(point(ox, oy, oz), vector(0, -sqrt(2) / 2, sqrt(2) / 2))
Пример #11
0
def step_create_ray_with_point_and_direction(context, ox, oy, oz, dx, dy, dz):
    context.r = Ray(point(ox, oy, oz), vector(dx, dy, dz))
Пример #12
0
#import the necessary modules
from core import Ray, Boundary, intersection, prop 
import numpy as np
import math

#establish the ray, boundary with desired info
#for now, the start points must be <= the endpoints, directionality of the code is an unsolved issue
#horizontal lines are not yet supported for boundary!
#to see results, pick ray/boundary so that they will intersect

ray = Ray([0,0], np.pi/6, 10)
boundary = Boundary([-10, -10], [10, 10], .75, 2)

#find out where the ray and boundary intersect
x_int, y_int = intersection(ray, boundary)

#split the ray after collision with the boundary
reflected_ray, refracted_ray = ray.split(boundary, [x_int, y_int])

print(reflected_ray.brightness)

#this will give you the corresponding ray info for the reflected & refracted rays after interaction with the first boundary
#required info can be accessed through the ray class, ex: reflected_ray.brightness()

#this is an unfinished build of core.py
#the finished version would ideally require the definition of parameters for ray/boundary, 
#and the rest would be automated through prop(ray)