Esempio n. 1
0
def out_dir(indir, n, mat):
    u = ti.Vector([1.0, 0.0, 0.0])
    if mat == mat_lambertian:
        if abs(n[1]) < 1 - eps:
            u = ti.normalized(ti.cross(n, ti.Vector([0.0, 1.0, 0.0])))
        v = ti.cross(n, u)
        phi = 2 * math.pi * ti.random()
        ay = ti.sqrt(ti.random())
        ax = ti.sqrt(1 - ay**2)
        u = ax * (ti.cos(phi) * u + ti.sin(phi) * v) + ay * n
    elif mat == mat_metal:
        u = reflect(indir, n)
    else:
        # glass
        cos = ti.dot(indir, n)
        ni_over_nt = refr_idx
        outn = n
        if cos > 0.0:
            outn = -n
            cos = refr_idx * cos
        else:
            ni_over_nt = 1.0 / refr_idx
            cos = -cos
        has_refr, refr_dir = refract(indir, outn, ni_over_nt)
        refl_prob = 1.0
        if has_refr:
            refl_prob = schlick(cos, refr_idx)
        if ti.random() < refl_prob:
            u = reflect(indir, n)
        else:
            u = refr_dir
    return ti.normalized(u)
Esempio n. 2
0
def next_hit(pos, d):
    closest, normal = inf, ti.Vector.zero(ti.f32, 3)
    c, mat = ti.Vector.zero(ti.f32, 3), mat_lambertian

    # right near sphere
    cur_dist, hit_pos = intersect_sphere(pos, d, sp1_center, sp1_radius)
    if 0 < cur_dist < closest:
        closest = cur_dist
        normal = ti.normalized(hit_pos - sp1_center)
        c, mat = ti.Vector([1.0, 1.0, 1.0]), mat_glass
    # left far sphere
    cur_dist, hit_pos = intersect_sphere(pos, d, sp2_center, sp2_radius)
    if 0 < cur_dist < closest:
        closest = cur_dist
        normal = ti.normalized(hit_pos - sp2_center)
        c, mat = ti.Vector([0.8, 0.5, 0.4]), mat_metal
    # left
    pnorm = ti.Vector([1.0, 0.0, 0.0])
    cur_dist, _ = ray_plane_intersect(pos, d, ti.Vector([-1.0, 0.0, 0.0]),
                                      pnorm)
    if 0 < cur_dist < closest:
        closest = cur_dist
        normal = pnorm
        c, mat = ti.Vector([1.0, 0.0, 0.0]), mat_lambertian
    # right
    pnorm = ti.Vector([-1.0, 0.0, 0.0])
    cur_dist, _ = ray_plane_intersect(pos, d, ti.Vector([1.0, 0.0, 0.0]),
                                      pnorm)
    if 0 < cur_dist < closest:
        closest = cur_dist
        normal = pnorm
        c, mat = ti.Vector([0.0, 1.0, 0.0]), mat_lambertian
    # bottom
    pnorm = ti.Vector([0.0, 1.0, 0.0])
    cur_dist, _ = ray_plane_intersect(pos, d, ti.Vector([0.0, 0.0, 0.0]),
                                      pnorm)
    if 0 < cur_dist < closest:
        closest = cur_dist
        normal = pnorm
        c, mat = ti.Vector([1.0, 1.0, 1.0]), mat_lambertian
    # top
    pnorm = ti.Vector([0.0, -1.0, 0.0])
    cur_dist, _ = ray_plane_intersect(pos, d, ti.Vector([0.0, 2.0, 0.0]),
                                      pnorm)
    if 0 < cur_dist < closest:
        closest = cur_dist
        normal = pnorm
        c, mat = ti.Vector([1.0, 1.0, 1.0]), mat_lambertian
    # far
    pnorm = ti.Vector([0.0, 0.0, 1.0])
    cur_dist, _ = ray_plane_intersect(pos, d, ti.Vector([0.0, 0.0, 0.0]),
                                      pnorm)
    if 0 < cur_dist < closest:
        closest = cur_dist
        normal = pnorm
        c, mat = ti.Vector([1.0, 1.0, 1.0]), mat_lambertian

    return closest, normal, c, mat
Esempio n. 3
0
def render():
    for u, v in color_buffer:
        aspect_ratio = res[0] / res[1]
        pos = camera_pos
        d = ti.Vector([
            (2 * fov * (u + ti.random()) / res[1] - fov * aspect_ratio - 1e-5),
            2 * fov * (v + ti.random()) / res[1] - fov - 1e-5, -1.0
        ])
        d = ti.normalized(d)

        throughput = ti.Vector([1.0, 1.0, 1.0])

        depth = 0
        hit_light = 0.00

        while depth < max_ray_depth:
            closest, normal, c = next_hit(pos, d)
            depth += 1
            dist_to_light = intersect_light(pos, d)
            if dist_to_light < closest:
                hit_light = 1
                depth = max_ray_depth
            else:
                hit_pos = pos + closest * d
                if normal.norm_sqr() != 0:
                    d = out_dir(normal)
                    pos = hit_pos + 1e-4 * d
                    throughput *= c
                else:
                    depth = max_ray_depth
        color_buffer[u, v] += throughput * hit_light
Esempio n. 4
0
def sample_ray_dir(indir, normal, hit_pos, mat):
    u = ti.Vector([0.0, 0.0, 0.0])
    pdf = 1.0
    if mat == mat_lambertian:
        u = sample_brdf(normal)
        pdf = max(eps, compute_brdf_pdf(normal, u))
    elif mat == mat_specular:
        u = reflect(indir, normal)
    elif mat == mat_glass:
        cos = indir.dot(normal)
        ni_over_nt = refr_idx
        outn = normal
        if cos > 0.0:
            outn = -normal
            cos = refr_idx * cos
        else:
            ni_over_nt = 1.0 / refr_idx
            cos = -cos
        has_refr, refr_dir = refract(indir, outn, ni_over_nt)
        refl_prob = 1.0
        if has_refr:
            refl_prob = schlick(cos, refr_idx)
        if ti.random() < refl_prob:
            u = reflect(indir, normal)
        else:
            u = refr_dir
    return ti.normalized(u), pdf
Esempio n. 5
0
def sdf_normal(p):
    d = 1e-3
    n = ti.Vector([0.0, 0.0, 0.0])
    sdf_center = sdf(p)
    for i in ti.static(range(3)):
        inc = p
        inc[i] += d
        n[i] = (1 / d) * (sdf(inc) - sdf_center)
    return ti.normalized(n)
Esempio n. 6
0
def out_dir(n):
    u = ti.Vector([1.0, 0.0, 0.0])
    if abs(n[1]) < 1 - eps:
        u = ti.normalized(ti.cross(n, ti.Vector([0.0, 1.0, 0.0])))
    v = ti.cross(n, u)
    phi = 2 * math.pi * ti.random()
    ay = ti.sqrt(ti.random())
    ax = ti.sqrt(1 - ay**2)
    return ax * (ti.cos(phi) * u + ti.sin(phi) * v) + ay * n
Esempio n. 7
0
    def voxelize_triangles(self, num_triangles: ti.i32,
                           triangles: ti.ext_arr()):
        for i in range(num_triangles):
            jitter_scale = ti.cast(0, self.precision)
            if ti.static(self.precision is ti.f32):
                jitter_scale = 1e-4
            else:
                jitter_scale = 1e-8
            # We jitter the vertices to prevent voxel samples from lying precicely at triangle edges
            jitter = ti.Vector([-0.057616723909439505, -0.25608986292614977, 0.06716309129743714]) * jitter_scale
            a = ti.Vector([triangles[i, 0], triangles[i, 1], triangles[i, 2]]) + jitter
            b = ti.Vector([triangles[i, 3], triangles[i, 4], triangles[i, 5]]) + jitter
            c = ti.Vector([triangles[i, 6], triangles[i, 7], triangles[i, 8]]) + jitter

            bound_min = ti.Vector.zero(self.precision, 3)
            bound_max = ti.Vector.zero(self.precision, 3)
            for k in ti.static(range(3)):
                bound_min[k] = min(a[k], b[k], c[k])
                bound_max[k] = max(a[k], b[k], c[k])

            p_min = int(ti.floor(bound_min[0] * self.inv_dx))
            p_max = int(ti.floor(bound_max[0] * self.inv_dx)) + 1
            
            p_min = max(self.padding, p_min)
            p_max = min(self.res[0] - self.padding, p_max)

            q_min = int(ti.floor(bound_min[1] * self.inv_dx))
            q_max = int(ti.floor(bound_max[1] * self.inv_dx)) + 1
            
            q_min = max(self.padding, q_min)
            q_max = min(self.res[1] - self.padding, q_max)

            normal = ti.normalized(ti.cross(b - a, c - a))
            
            if abs(normal[2]) < 1e-10:
                continue

            a_proj = ti.Vector([a[0], a[1]])
            b_proj = ti.Vector([b[0], b[1]])
            c_proj = ti.Vector([c[0], c[1]])

            for p in range(p_min, p_max):
                for q in range(q_min, q_max):
                    pos2d = ti.Vector([(p + 0.5) * self.dx, (q + 0.5) * self.dx])
                    if inside_ccw(pos2d, a_proj, b_proj, c_proj) or inside_ccw(pos2d, a_proj, c_proj, b_proj):
                        base_voxel = ti.Vector([pos2d[0], pos2d[1], 0])
                        height = int(
                            -ti.dot(normal, base_voxel - a) /
                            normal[2] * self.inv_dx + 0.5)
                        height = min(height, self.res[1] - self.padding)
                        inc = 0
                        if normal[2] > 0:
                            inc = 1
                        else:
                            inc = -1
                        self.fill(p, q, height, inc)
Esempio n. 8
0
def refract(d, n, ni_over_nt):
    # Assuming |d| and |n| are normalized
    has_r, rd = 0, d
    dt = ti.dot(d, n)
    discr = 1.0 - ni_over_nt * ni_over_nt * (1.0 - dt * dt)
    if discr > 0.0:
        has_r = 1
        rd = ti.normalized(ni_over_nt * (d - n * dt) - n * ti.sqrt(discr))
    else:
        rd *= 0.0
    return has_r, rd
Esempio n. 9
0
def render():
    for u, v in color_buffer:
        aspect_ratio = res[0] / res[1]
        pos = camera_pos
        cur_iter = count_var[0]
        str_x, str_y = (cur_iter / stratify_res), (cur_iter % stratify_res)
        ray_dir = ti.Vector([
            (2 * fov * (u + (str_x + ti.random()) * inv_stratify) / res[1] -
             fov * aspect_ratio - 1e-5),
            (2 * fov * (v + (str_y + ti.random()) * inv_stratify) / res[1] -
             fov - 1e-5),
            -1.0,
        ])
        ray_dir = ti.normalized(ray_dir)

        acc_color = ti.Vector([0.0, 0.0, 0.0])
        throughput = ti.Vector([1.0, 1.0, 1.0])

        depth = 0
        while depth < max_ray_depth:
            closest, hit_normal, hit_color, mat = intersect_scene(pos, ray_dir)
            if mat == mat_none:
                break

            hit_pos = pos + closest * ray_dir
            hit_light = (mat == mat_light)
            if hit_light:
                acc_color += throughput * light_color
                break
            elif mat == mat_lambertian:
                acc_color += throughput * sample_direct_light(
                    hit_pos, hit_normal, hit_color)

            depth += 1
            ray_dir, pdf = sample_ray_dir(ray_dir, hit_normal, hit_pos, mat)
            pos = hit_pos + 1e-4 * ray_dir
            if mat == mat_lambertian:
                throughput *= lambertian_brdf * hit_color * dot_or_zero(
                    hit_normal, ray_dir) / pdf
            else:
                throughput *= hit_color
        color_buffer[u, v] += acc_color
    count_var[0] = (count_var[0] + 1) % (stratify_res * stratify_res)
Esempio n. 10
0
def grid_op():
    for i, j in grid_m:
        if grid_m[i, j] > 0:
            inv_m = 1 / grid_m[i, j]
            v_out = inv_m * grid_v_in[i, j]  # momentum to velocity
            v_out[1] -= dt * gravity  # gravity

            # center sticky circle
            dist = ti.Vector([i * dx - 0.5, j * dx - 0.5])
            if dist.norm_sqr() < 0.005:
                dist = ti.normalized(dist)
                v_out -= dist * ti.dot(v_out, dist)

            # boundary conditions
            if i < bound and v_out[0] < 0:
                v_out[0] = 0
            if i > n_grid - bound and v_out[0] > 0:
                v_out[0] = 0
            if j < bound and v_out[1] < 0:
                v_out[1] = 0
            if j > n_grid - bound and v_out[1] > 0:
                v_out[1] = 0

            grid_v_out[i, j] = v_out
Esempio n. 11
0
def sample_area_light(hit_pos, pos_normal):
    # sampling inside the light area
    x = ti.random() * light_x_range + light_x_min_pos
    z = ti.random() * light_z_range + light_z_min_pos
    on_light_pos = ti.Vector([x, light_y_pos, z])
    return ti.normalized(on_light_pos - hit_pos)
Esempio n. 12
0
def intersect_scene(pos, ray_dir):
    closest, normal = inf, ti.Vector.zero(ti.f32, 3)
    c, mat = ti.Vector.zero(ti.f32, 3), mat_none

    # right near sphere
    cur_dist, hit_pos = intersect_sphere(pos, ray_dir, sp1_center, sp1_radius)
    if 0 < cur_dist < closest:
        closest = cur_dist
        normal = ti.normalized(hit_pos - sp1_center)
        c, mat = ti.Vector([1.0, 1.0, 1.0]), mat_glass
    # left box
    hit, cur_dist, pnorm = ray_aabb_intersection2_transformed(
        box_min, box_max, pos, ray_dir)
    if hit and 0 < cur_dist < closest:
        closest = cur_dist
        normal = pnorm
        c, mat = ti.Vector([0.8, 0.5, 0.4]), mat_specular

    # left
    pnorm = ti.Vector([1.0, 0.0, 0.0])
    cur_dist, _ = ray_plane_intersect(pos, ray_dir, ti.Vector([-1.1, 0.0,
                                                               0.0]), pnorm)
    if 0 < cur_dist < closest:
        closest = cur_dist
        normal = pnorm
        c, mat = ti.Vector([0.65, 0.05, 0.05]), mat_lambertian
    # right
    pnorm = ti.Vector([-1.0, 0.0, 0.0])
    cur_dist, _ = ray_plane_intersect(pos, ray_dir, ti.Vector([1.1, 0.0, 0.0]),
                                      pnorm)
    if 0 < cur_dist < closest:
        closest = cur_dist
        normal = pnorm
        c, mat = ti.Vector([0.12, 0.45, 0.15]), mat_lambertian
    # bottom
    gray = ti.Vector([0.93, 0.93, 0.93])
    pnorm = ti.Vector([0.0, 1.0, 0.0])
    cur_dist, _ = ray_plane_intersect(pos, ray_dir, ti.Vector([0.0, 0.0, 0.0]),
                                      pnorm)
    if 0 < cur_dist < closest:
        closest = cur_dist
        normal = pnorm
        c, mat = gray, mat_lambertian
    # top
    pnorm = ti.Vector([0.0, -1.0, 0.0])
    cur_dist, _ = ray_plane_intersect(pos, ray_dir, ti.Vector([0.0, 2.0, 0.0]),
                                      pnorm)
    if 0 < cur_dist < closest:
        closest = cur_dist
        normal = pnorm
        c, mat = gray, mat_lambertian
    # far
    pnorm = ti.Vector([0.0, 0.0, 1.0])
    cur_dist, _ = ray_plane_intersect(pos, ray_dir, ti.Vector([0.0, 0.0, 0.0]),
                                      pnorm)
    if 0 < cur_dist < closest:
        closest = cur_dist
        normal = pnorm
        c, mat = gray, mat_lambertian
    # light
    hit_l, cur_dist = intersect_light(pos, ray_dir, closest)
    if hit_l and 0 < cur_dist < closest:
        # technically speaking, no need to check the second term
        closest = cur_dist
        normal = light_normal
        c, mat = light_color, mat_light

    return closest, normal, c, mat
Esempio n. 13
0
def paint(t: ti.f32):
    fin = ti.Vector([0.0, 0.0, 0.0])  # Parallized over all pixels
    intensity = 0.0

    for i in range(n * 16):  #this is parallilized
        for j in range(n * 9):
            for x in range(3):
                uv = ti.Vector([((i / (16 * n)) - 0.5) * (2),
                                (j / (9 * n)) - 0.5])

                starting_y = 17.0
                ending_y = 5.0
                motion_y = -t
                lookat_starting_y = 17.0
                lookat_ending_y = 5.0
                # motion_y = 0

                ro = ti.Vector([5.0, starting_y, 1.0])
                lookat = ti.Vector([5.0, lookat_starting_y, 6.0])

                if starting_y + motion_y > ending_y:
                    ro = ti.Vector([5.0, starting_y + motion_y, 1.0])
                    lookat = ti.Vector(
                        [5.0, lookat_starting_y + motion_y, 6.0])
                else:
                    ro = ti.Vector([5.0, ending_y, 1.0])
                    lookat = ti.Vector([5.0, lookat_ending_y, 6.0])

                zoom = 1.0

                forward = ti.normalized(lookat - ro)
                right = ti.cross(ti.Vector([0.0, 1.0, 0.0]), forward)
                up = ti.cross(forward, right)

                center = ro + forward * zoom
                intersection = center + uv[0] * right + uv[1] * up
                rd = ti.normalized(intersection - ro)

                d, no, intersection_object, clouddO, cloud_intersection, clouddO2, cloud_intersection2, clouddO3, cloud_intersection3, sdf, sdf_inter = rayCast(
                    ro, rd, t, frameTimeBlur * x)
                p = ro + rd * d
                light, normal = GetLight(p, t, intersection_object, no,
                                         frameTimeBlur * x, rd)

                if x == 0:
                    sdf_p = ro + rd * sdf
                    sdf_light, normal_sdf = GetLight(sdf_p, t, sdf_inter, no,
                                                     frameTimeBlur * x, rd)
                    # if (intersection_object == CAPSULE):
                    #     rd2 = reflect(rd, normal)
                    #     d2, no2, intersection_object2 = rayCast_reflection(ro +  normal*.003, rd2, t+(0.03*0), 0.03*0)

                    #     p += rd2*d2

                    #     light2, normal2 = GetLight(p, t, intersection_object2, no2, frameTimeBlur*x, rd2)
                    #     sdf_light += light2*0.30

                    pixels[i, j] = ti.Vector(
                        [sdf_light[0], sdf_light[1], sdf_light[2],
                         1.0])  #color

                alpha = 0.8
                alpha1 = 0.4
                alpha2 = 0.2
                if intersection_object == PARTICLES:
                    if x == 0:
                        #doing pixel = pixels + ... to add the particle color value on top of the background
                        pixels[i, j] = pixels[i, j] * alpha + ti.Vector([
                            light[0], light[1], light[2], 1.0 / (1.0 - alpha)
                        ]) * (1.0 - alpha)
                    if x == 1:
                        pixels[i, j] = pixels[i, j] * alpha1 + ti.Vector([
                            light[0], light[1], light[2], 1.0 / (1.0 - alpha1)
                        ]) * (1.0 - alpha1)
                    if x == 2:
                        pixels[i, j] = pixels[i, j] * alpha2 + ti.Vector([
                            light[0], light[1], light[2], 1.0 / (1.0 - alpha2)
                        ]) * (1.0 - alpha2)

                if x == 2:
                    if cloud_intersection == 1:
                        p_cloud = ro + rd * clouddO
                        light_cloud, normal_cloud = GetLight(
                            p_cloud, t, CLOUD, no, 0, rd)
                        pixels[i, j] = pixels[i, j] + ti.Vector([
                            light_cloud[0] * 0.30, light_cloud[1] * 0.30,
                            light_cloud[2] * 0.30, 1.0
                        ])
                    if cloud_intersection3 == 1:
                        p_cloud3 = ro + rd * clouddO3
                        light_cloud3, normal_cloud3 = GetLight(
                            p_cloud3, t, CLOUD3, no, 0, rd)
                        pixels[i, j] = pixels[i, j] + ti.Vector([
                            light_cloud3[0] * 0.30, light_cloud3[1] * 0.30,
                            light_cloud3[2] * 0.30, 1.0
                        ])
                    if cloud_intersection2 == 1:
                        p_cloud2 = ro + rd * clouddO2
                        light_cloud2, normal_cloud2 = GetLight(
                            p_cloud2, t, CLOUD2, no, 0, rd)
                        pixels[i, j] = pixels[i, j] + ti.Vector([
                            light_cloud2[0] * 0.30, light_cloud2[1] * 0.30,
                            light_cloud2[2] * 0.30, 1.0
                        ])