def scatter(self, rIn, rec): attenuation = vec3(1, 1, 1) etaiOverEtat = (1.0 / self.refIndex) if rec.frontFace else self.refIndex unitDirection = vec3.normalize(rIn.direction()) cosTheta = min(vec3.dot(unitDirection * -1, rec.n), 1.0) sinTheta = math.sqrt(1.0 - cosTheta * cosTheta) # TIR if etaiOverEtat * sinTheta > 1.0: reflected = vec3.reflect(unitDirection, rec.n) scattered = ray(rec.p, reflected) return (attenuation, scattered) # prop. reflection / refraction reflectProb = dielectric.schlick(cosTheta, etaiOverEtat) # reflection if random.random() < reflectProb: reflected = vec3.reflect(unitDirection, rec.n) scattered = ray(rec.p, reflected) return (attenuation, scattered) # refraction refracted = vec3.refract(unitDirection, rec.n, etaiOverEtat) scattered = ray(rec.p, refracted) return (attenuation, scattered)
def scatter_ray(self, incident_ray, hit_rec, attenuate, scatterd_ray): no_attenuation = vector_3d([1.0, 1.0, 1.0]) ir_direction = incident_ray.direction() reflected_ray = reflect_a_ray(ir_direction, hit_rec.normal_) if dot_product(ir_direction, hit_rec.normal_) > 0: out_normal = -hit_rec.normal_ ni_over_nr = self.ref_idx_ cos_theta = (self.ref_idx_ * dot_product(ir_direction, hit_rec.normal_))/(ir_direction.length()) else: out_normal = hit_rec.normal_ ni_over_nr = (1.0 / self.ref_idx_) cos_theta = -dot_product(ir_direction, hit_rec.normal_)/(ir_direction.length()) # end: if dot_product(....) > 0 # is the ray reflected ? ray_is_refracted, refracted_ray = refract_a_ray(ir_direction, out_normal, ni_over_nr) reflect_chance = 1.0 if ray_is_refracted == True: reflect_chance = self.schlick_approx(cos_theta) if random.random() < reflect_chance: new_ray = ray(hit_rec.p_, reflected_ray) else: new_ray = ray(hit_rec.p_, refracted_ray) # copy the values back attenuate.values_ = no_attenuation.values_ scatterd_ray.origin_ = new_ray.origin_ scatterd_ray.direction_ = new_ray.direction_ return True
def scatter(self, r_in, rec, attenuation): refracted = np.zeros([3], dtype=np.float32) reflected = reflect(r_in.direction(), rec.normal) attenuation = np.array([1, 1, 1], dtype=np.float32) 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) / length(r_in.direction()) # cosine = np.dot(r_in.direction(), rec.normal) / length(r_in.direction()) # print(1 - self.ref_idx * self.ref_idx * (1 - cosine ** 2), self.ref_idx, cosine) # cosine = math.sqrt(1 - self.ref_idx * self.ref_idx * (1 - cosine ** 2)) else: outward_normal = rec.normal ni_over_nt = 1.0 / self.ref_idx cosine = (0 - np.dot(r_in.direction(), rec.normal)) / length( r_in.direction()) boolean, refracted = refract(r_in.direction(), outward_normal, ni_over_nt, refracted) if boolean: 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 True, attenuation, scattered
def scatter(self, r_in: ray, rec, attenuation: glm.vec3, scattered: ray) -> bool: _att = glm.vec3(1., 1., 1.) attenuation.x, attenuation.y, attenuation.z = _att.x, _att.y, _att.z etai_over_etat = 1 / self.ref_ind if rec.front_face else self.ref_ind cos_theta = glm.fmin( glm.dot(-glm.normalize(r_in.direction()), rec.normal), 1.) sin_theta = glm.sqrt(1. - cos_theta * cos_theta) refracted_or_reflected = None if sin_theta * etai_over_etat > 1.: refracted_or_reflected = reflect(glm.normalize(r_in.direction()), rec.normal) else: refracted_or_reflected = refract(glm.normalize(r_in.direction()), rec.normal, etai_over_etat) _scattered = ray(rec.p, refracted_or_reflected) scattered.orig = _scattered.origin() scattered.direc = _scattered.direction() return True
def colorize_world(R, world_object_list, reflection_depth = 0): ''' colorize the world of objects with a specific reflection-depth. this implies that the ray 'R' is reflected utmost 'reflection_depth' times. ''' rec = hit_record(0.0, vector_3d(), vector_3d(), None) boundary = hit_boundary(0.001, sys.float_info.max) if world_object_list.hit(R, boundary, rec): # hit scattered_ray = ray() attenuation = vector_3d() # did this ray get scattered around ? is_scatterd = rec.material_.scatter_ray(R, rec, attenuation, scattered_ray) if reflection_depth < 50 and is_scatterd == True: color = attenuation * colorize_world(scattered_ray, world_object_list, reflection_depth + 1) else: color = vector_3d() else: # no hit unit_dir = create_unit_vector(R.direction()) t = 0.5 * (unit_dir.y() + 1.0) color = (1.0 - t) * vector_3d([1.0, 1.0, 1.0]) + t * vector_3d([0.5, 0.7, 1.0]) return color
def is_shadowed(self, site): """ takes in world and a point and returns if it shaded or not """ vector_to_light = (self.Lights()[0].Position() - site) distance = vector_to_light.magnitude() # now normalize the vector vector_to_light = vector_to_light.normalize() ray_to_light = ray(site, vector_to_light) junctions = self.intersect_world(ray_to_light) h = IdentifyHit(junctions) # new = [] # for crossing in junctions: # commit = Intersection(crossing['time'], crossing['object']) # new.append(commit) # print(new[0].t) # i = Intersections(new) # h = i.hit() # gets the most relevant hit if h and h['time'] < distance: return True else: return False
def raytrace(r, scene, depth): # Determine the closest hits distances = [s.intersect(r, 0.001, 1.0e39) for s in scene] nearest = ft.reduce(np.minimum, distances) # Ambient color = rgb(0.0, 0.0, 0.0) unit_dir = unit_vector(r.direction()) t = (unit_dir.y + 1.0) * 0.5 # bgc = (vec3(1.0, 1.0, 1.0)*(1.0 - t) + vec3(0.5, 0.7, 1.0)*t) bgc = vec3(0.5, 0.7, 1.0) * t for (s, d) in zip(scene, distances): hit = (nearest != 1.0e39) & (d == nearest) print("depth: %s | Radius: %s | Shape: %s" % (depth, s.radius, hit.shape)) time.sleep(0.1) if np.any(hit) and depth < 5: dc = np.extract(hit, d) oc = r.origin().extract(hit) dirc = r.direction().extract(hit) er = ray(oc, dirc) p = er.point_at_parameter(dc) N = (p - s.center) / vec3(s.radius, s.radius, s.radius) shader = s.material() scattered = shader.scatter(er, p, N) cc = raytrace(scattered, scene, depth + 1) * shader.albedo # cc = vec3(shader.albedo, shader.albedo, shader.albedo) color += cc.place2(hit, bgc) return color
def run(self): dx, dy = self.decenter x = self.ray.x - dx y = self.ray.y - dy z = self.ray.z R = self.R() K, L, M = R.dot(np.array([self.ray.K, self.ray.L, self.ray.M])) return ray(x, y, z, K, L, M)
def scatter(self, rIn, rec): reflected = vec3.reflect(vec3.normalize(rIn.direction()), rec.n) scattered = ray(rec.p, reflected + vec3.randomPointInSphere() * self.fuzz) if vec3.dot(scattered.direction(), rec.n) > 0: return (self.color, scattered) else: return None
def get_ray(self, U, V): rd = self.lens_radius_ * self.random_in_unit_disk_() offset = self.u_ * rd.x() + self.v_ * rd.y() return ray(self.origin_ + offset, (self.lower_left_corner_ + U * self.horizontal_span_ + V * self.vertical_span_ - self.origin_ - offset))
def getRay(self, u, v): temp = vec3.randomPointInDisc() * self.lenseRadius apertureOffset = self.u * temp.x() + self.v * temp.y() return ray( self.lookFrom + apertureOffset, self.lowerLeftCorner + self.u * u * 2 * self.halfWidth + self.v * v * 2 * self.halfHeight - (self.lookFrom + apertureOffset))
def unrun(self): dx, dy = self.decenter x = self.ray.x + dx y = self.ray.y + dy z = self.ray.z R = self.R(sign=-1) K, L, M = R.dot(np.array([self.ray.K, self.ray.L, self.ray.M])) return ray(x, y, z, K, L, M)
def scatter_ray(self, incident_ray, hit_rec, attenuate, scatterd_ray): target = hit_rec.p_ + hit_rec.normal_ + random_point_in_unit_sphere() new_ray = ray(hit_rec.p_, target - hit_rec.p_) # copy the values back attenuate.values_ = self.albedo_.values_ scatterd_ray.origin_ = new_ray.origin_ scatterd_ray.direction_ = new_ray.direction_ return True
def scatter(self, r_in: ray, rec, attenuation: glm.vec3, scattered: ray) -> bool: scatter_direction = rec.normal + random_unit_vector() _scattered = ray(rec.p, scatter_direction) scattered.orig = _scattered.origin() scattered.direc = _scattered.direction() _albedo_corr = self.albedo.value(rec.u, rec.v, rec.p) attenuation.x, attenuation.y, attenuation.z = _albedo_corr.x, _albedo_corr.y, _albedo_corr.z return True
def reflected_color(world, comps, remaining=LIMIT): if remaining <= 0: return color(0, 0, 0) else: if comps.object.material.reflective == 0: return color(0, 0, 0) else: reflect_ray = ray(comps.over_point, comps.reflectv) remaining -= 1 c = color_at(world, reflect_ray, remaining) return c * comps.object.material.reflective
def get_ray(self, u, v): nu = self.horz * u nv = self.vert * v l = nu.components()[0].shape ox = np.repeat(self.origin.x, l) oy = np.repeat(self.origin.y, l) oz = np.repeat(self.origin.z, l) no = vec3(ox, oy, oz) direction = self.llc + nu + nv - no return ray(no, direction)
def ray_for_pixel(camera, px, py): xoffset = (px + 0.5) * camera.pixel_size yoffset = (py + 0.5) * camera.pixel_size world_x = camera.half_width - xoffset world_y = camera.half_height - yoffset pixel = inverse(camera.transform) * point(world_x, world_y, -1) origin = inverse(camera.transform) * point(0, 0, 0) direction = normalize(pixel - origin) return ray(origin, direction)
def is_shadowed(world, point): v = world.light.position - point distance = magnitude(v) direction = normalize(v) r = ray(point, direction) intersections = intersect_world(world, r) h = hit(intersections) if h is not None and h.t < distance: return True else: return False
def scatter_ray(self, incident_ray, hit_rec, attenuate, scatterd_ray): reflected_ray = reflect_a_ray(create_unit_vector(incident_ray.direction()), hit_rec.normal_) new_ray = ray(hit_rec.p_, reflected_ray + self.fuzz_ * random_point_in_unit_sphere()) # copy the values back attenuate.values_ = self.albedo_.values_ scatterd_ray.origin_ = new_ray.origin_ scatterd_ray.direction_ = new_ray.direction_ # is it scattered ? if dot_product(scatterd_ray.direction(), hit_rec.normal_) > 0: return True return False
def scatter(self, r_in: ray, rec, attenuation: glm.vec3, scattered: ray) -> bool: reflected = reflect(glm.normalize(r_in.direction()), rec.normal) _scattered = ray(rec.p, reflected + self.fuzz * random_in_unit_sphere()) scattered.orig = _scattered.origin() scattered.direc = _scattered.direction() _albedo_corr = self.albedo.value(rec.u, rec.v, rec.p) attenuation.x, attenuation.y, attenuation.z = _albedo_corr.x, _albedo_corr.y, _albedo_corr.z return glm.dot(scattered.direction(), rec.normal) > 0
def ray_for_pixel(self, px, py): xoffset = (px + 0.5) * self.Get_Pixel_Size() yoffset = (py + 0.5) * self.Get_Pixel_Size() world_x = self.Half_Width() - xoffset world_y = self.Half_Height() - yoffset pixel = self.set_transform.inverse().multiply_tuple( point(world_x, world_y, -1)) origin = self.set_transform.inverse().multiply_tuple(point(0, 0, 0)) direction = pixel - origin direction = direction.normalize() return ray(origin, direction)
def initialize(self, coordinates, directions): ''' Initialize the rays coordinates: An iterable data structure of (x, y, z) directions: An iterable data structure of (xvec, yvec, zvec) ''' assert len(coordinates) == len(directions) == self.numofrays self.__directions = directions index = self.indef['init'] for (x, y, z) in coor: r = ray() r.unlock() r.addPoint(x, y, z, index) r.lock() self.rays.append(r)
def color_at(self, obj_hit, hit_pos, normal, scene): mat = obj_hit.material obj_color = mat.color_at(hit_pos) specular_k = 1.5 to_cam = scene.camera - hit_pos c = mat.ambient * color.from_hex("#000000") for light in scene.lights: to_light = ray(hit_pos, light.position - hit_pos) #Освещение по Ламберту c = c + obj_color * mat.diffuse * max( normal.dot_product(to_light.direction), 0) #Blin-Phong lightinig half_vector = (to_light.direction + to_cam).normolize() c = c + light.color * mat.specular * max( normal.dot_product(half_vector), 0)**specular_k return c
def refracted_color(world, comps, remaining): if comps.object.material.transparency == 0 or remaining <= 0: return color(0, 0, 0) else: n_ratio = comps.n1 / comps.n2 cos_i = dot(comps.eyev, comps.normalv) sin2_t = n_ratio ** 2 * (1 - cos_i ** 2) if sin2_t > 1: return color(0, 0, 0) else: cos_t = sqrt(1.0 - sin2_t) direction = comps.normalv * (n_ratio * cos_i - cos_t) - comps.eyev * n_ratio refract_ray = ray(comps.under_point, direction) c = ( color_at(world, refract_ray, remaining - 1) * comps.object.material.transparency ) return c
def _standard(self): '''refract at spherical surface "surf"''' C = 1 / self.surf2.radius n0 = self.surf1.index[self.wave] n1 = self.surf2.index[self.wave] e = -self.ray.x * self.ray.K - self.ray.y * self.ray.L - self.ray.z * self.ray.M Mz = self.ray.z + e * self.ray.M M2 = self.ray.x**2 + self.ray.y**2 + self.ray.z**2 - e**2 arg = self.ray.M**2 - C * (C * M2 - 2 * Mz) if arg < 0: print('Warning: Total internal reflection occurs on surface %d' % self.surf2.number) E1 = np.sqrt(arg) Ep = np.sqrt(1 - (n0 / n1)**2 * (1 - E1**2)) g = Ep - n0 / n1 * E1 K1 = n0 / n1 * self.ray.K - g * C * self.ray.x L1 = n0 / n1 * self.ray.L - g * C * self.ray.y M1 = n0 / n1 * self.ray.M - g * C * self.ray.z + g return ray(self.ray.x, self.ray.y, self.ray.z, K1, L1, M1)
def simpleRaycast(): t0 = time.time() nx = 200 ny = 100 # Build array of vectors defined on a normalized plane # aspect ratio r = float(nx) / float(ny) # normalized range S = (0., 1., 1., 0.) # linearly step through each xy pixel and create vector position npx = np.tile(np.linspace(S[0], S[2], nx), ny) npy = np.repeat(np.linspace(S[1], S[3], ny), nx) npz = np.repeat(0.0, (nx * ny)) origin = vec3(0.0, 0.0, 0.0) # test = ray(origin, lower_left_corner + npx*horizontal + npy*vertical) # print(test) Q = vec3(npx, npy, npz) rdir = Q - origin lower_left_corner = vec3(-2.0, -1.0, -1.0) horizontal = vec3(4.0, 0.0, 0.0) vertical = vec3(0.0, 2.0, 0.0) u = horizontal * rdir.x v = vertical * rdir.y direction = lower_left_corner + u + v iray = ray(origin, direction) colorRet = color(iray) print("Took %s" % (time.time() - t0)) from PIL import Image rgb = [ Image.fromarray( (255 * np.clip(c, 0, 1).reshape(ny, nx)).astype(np.uint8), "L") for c in colorRet.components() ] Image.merge("RGB", rgb).save("output/output_simpleRayCast.png")
def _standard(self, EP_transfer=False, **kwargs): '''transfer from point x,y,z with dir. cosines K,L,M to spherical surface "surf2"''' if EP_transfer: t = kwargs['t'] else: t = self.surf1.thickness C = 1 / self.surf2.radius e = t * self.ray.M - (self.ray.x * self.ray.K + self.ray.y * self.ray.L + self.ray.z * self.ray.M) Mz = self.ray.z + e * self.ray.M - t M2 = self.ray.x**2 + self.ray.y**2 + self.ray.z**2 - e**2 + t**2 - 2 * t * self.ray.z arg = self.ray.M**2 - C * (C * M2 - 2 * Mz) if arg < 0: print('Warning: Ray does not intersect surface %d' % self.surf2.number) E1 = np.sqrt(arg) OPL = e + (C * M2 - 2 * Mz) / (self.ray.M + E1) x1 = self.ray.x + OPL * self.ray.K y1 = self.ray.y + OPL * self.ray.L z1 = self.ray.z + OPL * self.ray.M - t OPL = OPL * self.surf1.index[self.wave] return ray(x1, y1, z1, self.ray.K, self.ray.L, self.ray.M, OPL=OPL)
def _asphere(self): '''refract at an aspheric surface''' C = 1 / self.surf2.radius n0 = self.surf1.index[self.wave] n1 = self.surf2.index[self.wave] r2 = self.ray.x**2 + self.ray.y**2 m0 = np.sqrt(1 - C**2 * r2) arg = C + m0 * sum( [2 * (k + 1) * r2**k * a for k, a in enumerate(self.surf2.A)]) l0 = -self.ray.y * arg k0 = -self.ray.x * arg P2 = k0**2 + l0**2 + m0**2 F = self.ray.K * k0 + self.ray.L * l0 + self.ray.M * m0 arg = P2 * (1 - n0**2 / n1**2) + n0**2 / n1**2 * F**2 if arg < 0: print('Warning: Total internal reflection occurs on surface %d' % self.surf2.number) Fp = np.sqrt(arg) g = 1 / P2 * (Fp - n0 / n1 * F) K1 = n0 / n1 * self.ray.K + g * k0 L1 = n0 / n1 * self.ray.L + g * l0 M1 = n0 / n1 * self.ray.M + g * m0 return ray(self.ray.x, self.ray.y, self.ray.z, K1, L1, M1)
def main(): t0 = time.time() nx = 200 ny = 100 # Build array of vectors defined on a normalized plane # aspect ratio r = float(nx) / float(ny) # normalized range S = (0., 1., 1., 0.) # linearly step through each xy pixel and create vector position npx = np.tile(np.linspace(S[0], S[2], nx), ny) npy = np.repeat(np.linspace(S[1], S[3], ny), nx) npz = np.repeat(0.0, (nx * ny)) origin = vec3(0.0, 0.0, 0.0) # test = ray(origin, lower_left_corner + npx*horizontal + npy*vertical) # print(test) Q = vec3(npx, npy, npz) rdir = Q - origin lower_left_corner = vec3(-2.0, -1.0, -1.0) horizontal = vec3(4.0, 0.0, 0.0) vertical = vec3(0.0, 2.0, 0.0) u = horizontal * rdir.x v = vertical * rdir.y direction = lower_left_corner + u + v iray = ray(origin, direction) colorRet = color(iray) print("Took %s" % (time.time() - t0)) output_image(colorRet, nx, ny)
def render(self, scene): width = scene.width height = scene.height ascept_ratio = float(width) / height x0 = -1.0 x1 = +1.0 xstep = (x1 - x0) / (width - 1) y0 = -1.0 / ascept_ratio y1 = +1.0 / ascept_ratio ystep = (y1 - y0) / (height - 1) camera = scene.camera pixels = image(width, height) for j in range(height): y = y0 + j * ystep for i in range(width): x = x0 + i * xstep new_point = point(x, y) - camera #print(new_point) rey = ray(camera, new_point) pixels.set_pixel(i, j, self.ray_trace(rey, scene)) #progress bar print("{:3.0f}%".format(float(j) / float(height) * 100), end="\r") return pixels
## main process ## if __name__ == '__main__': ## initialize parameters ## w = 320 h = 240 PI = 3.14159265 view_angle = 60 * PI / 180.0 view_ratio = tan(view_angle/2) / (w/2.0) img_size = (w,h) im = Image.new("RGB", img_size, 'rgb(128,128,128)') draw = ImageDraw.Draw(im) ## objects in virtual space ## ''' set light ''' light = ray(vector3(1.0,-1.8,5.0), vector3(0.0,1.0,0.0)) ''' set eye position''' eye = vector3(0.0,0.0,-1.0) ''' primitive objects ''' obj_list = [] obj_list.append(face(vector3(0.0,-2.0,0.0), vector3(0.0,1.0,0.0), 255)) obj_list.append(face(vector3(0.0, 2.0,0.0), vector3(0.0,-1.0,0.0), 255<<8)) obj_list.append(face(vector3(-2.0,0.0,0.0), vector3(1.0,0.0,0.0), 255<<16)) obj_list.append(face(vector3( 2.0,0.0,0.0), vector3(-1.0,0.0,0.0), 255 + (255<<8))) obj_list.append(face(vector3(0.0,0.0,10.0), vector3(0.0,0.0,-1.0), 255 + (255<<8) + (255<<16))) obj_list.append(sphere(vector3(0.0,0.7,5.0), 1.5, 255 + (255<<16))) v_percentage = 1 ## each line ## for y in range(0,h): if v_percentage <= y*100 // h :
#print(len(self.activeRays)) nextRays = [] for dray in self.activeRays: # For every active ray, create the next rays for newRay in dray.interact(refraction_sim.c, self.dt, self.function): # For every created ray nextRays.append(newRay) # append it to the 'NextRays' list self.activeRays = nextRays # Update the 'activeRays' to the nextRays for dray in self.activeRays: # Time to draw the path the ray color, start, end = dray.draw() pygame.draw.line(screen, color, start, end, 2) #f = lambda v: 3-2*math.sin(.01*(v.x)) #f = lambda v: 5 - ((v.x - 600)**2 + (v.y - 600)**2)/200000 f = lambda v: 1 + 0.001*v.x rays = [] for i in range(0,3): rays.append(ray(vec(100,100), vec(1,1), 600+10*i, 1)) atmos = refraction_sim(f, rays, 1) screen.fill((0,0,0)) running = True while running: for event in pygame.event.get(): if event.type == pygame.QUIT: running = False atmos.take_step() pygame.display.flip() #pygame.time.wait(1000)
# shape.transform = rotation_z(pi / 4) * scaling(0.5, 1, 1) # shape.transform = shearing(1, 0, 0, 0, 0, 0) * scaling(0.5, 1, 1) start = time.time() print("Starting render...") 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(pos - ray_origin)) xs = intersect(shape, r) if hit(xs) is not None: pnt = position(r, xs[0].t) normal = normal_at(xs[0].object, pnt) eye = -r.direction color = lighting(xs[0].object.material, xs[0].object, light, pnt, eye, normal) write_pixel(canvas, x, y, color) end = time.time() print("Finished render.") print(str(round(end - start, 2)) + "s") start = time.time()
def colorize_plane(x_pixels, y_pixels): lower_left_corner = vector_3d([-2.0, -1.0, -1.0]) horizontal_span = vector_3d([4.0, 0.0, 0.0]) vertical_span = vector_3d([0.0, 2.0, 0.0]) origin = vector_3d() ppm_file_lines = [ ] # # the ppm preamble # P3 # 640 480 # 255 # ppm_file_lines.append("P3") ppm_file_lines.append('{:d} {:d}'.format(x_pixels, y_pixels)) ppm_file_lines.append("255") def ray_intersects_sphere(ray, sphere_center, sphere_radius): ''' return True if ray 'R' intersects a sphere (at 'sphere_center' and of size 'sphere_radius') ray-sphere-intersection is a quadratic equation, and we just check if the discriminant is > 0 ''' ray_dir = ray.direction() ray_origin = ray.origin() # # vector from ray-origin to sphere-center # [ray-origin] - [sphere-center] # oc = ray_origin - sphere_center # coefficients (ax^2 + bx + c) A = dot_product(ray_dir, ray_dir) B = 2.0 * dot_product(oc, ray_dir) C = dot_product(oc, oc) - (sphere_radius * sphere_radius) discriminant = (B*B - 4*A*C) if discriminant < 0: return -1.0 root_1 = (-B - math.sqrt(discriminant))/(2.0 * A) return root_1 def colorize_ray(R): ''' colorize a ray by linear-interpolation ''' pos, radius = vector_3d([0.0, 0.0, -1.0]), 0.5 t = ray_intersects_sphere(R, pos, radius) if t > 0: # surface-normal is in the direction of intersection (minus the center) normal_vec = create_unit_vector(R.point_on_ray(t) - pos) # shade stuff along the normal... color = 0.5 * vector_3d([normal_vec.x()+1, normal_vec.y()+1, normal_vec.z()+1]) else: unit_dir = create_unit_vector(R.direction()) t = 0.5 * (unit_dir.y() + 1.0) color = (1.0 - t) * vector_3d([1.0, 1.0, 1.0]) + t * vector_3d([0.5, 0.7, 1.0]) return color # draw the plane for y in range(y_pixels - 1, 0, -1): for x in range(0, x_pixels): # where does this pixel fall on the plane u = float(x)/float(x_pixels) v = float(y)/float(y_pixels) r = ray(origin, lower_left_corner + u*horizontal_span + v*vertical_span) point_color = 255.99 * colorize_ray(r) r, g, b = point_color.rgb_values() ppm_file_lines.append('{:d} {:d} {:d}'.format(r, g, b)) return ppm_file_lines
source_fn = calc_source_fn(source_fn, epsilon, J_n) import astropy.units as u # physical grid radial_grid = np.linspace(1, 10, n_depth_pts) * u.cm # opacity grid chi_grid = np.logspace(-7, 3, n_depth_pts) * (1/u.cm) # angular grid mu_grid = np.linspace(-1, 1, n_mu_pts) rays = [] from ray import ray for mu in mu_grid: rays.append(ray(mu, n_depth_pts, radial_grid)) # let's get some useful (nonzero) values to start for each_ray in rays: each_ray.calc_tau(n_depth_pts, radial_grid, chi_grid) each_ray.formal_soln(n_depth_pts, source_fn) # build tri-diagonal component of Lambda matrix Lambda_star = np.zeros([n_depth_pts, n_depth_pts]) from calc_Lambda_star import calc_Lambda_star Lambda_star = calc_Lambda_star(Lambda_star, n_depth_pts, n_mu_pts, rays, mu_grid) # mean intensity from the formal solution J_fs = np.zeros(n_depth_pts)
def step_impl(context): context.r = ray(point(0, -1, 0), vector(0, 1, 0))
def get_ray(self, u, v) -> ray: return ray( self.origin, self.lower_left_corner + u * self.horizontal + v * self.vertical - self.origin)
# shape.transform = rotation_z(pi / 4) * scaling(0.5, 1, 1) # shape.transform = shearing(1, 0, 0, 0, 0, 0) * scaling(0.5, 1, 1) start = time.time() print("Starting render...") for y in range(canvas_pixels): world_y = half - pixel_size * y for x in range(canvas_pixels): world_x = -half + pixel_size * x position = point(world_x, world_y, wall_z) r = ray(ray_origin, normalize(position - ray_origin)) xs = intersect(shape, r) if hit(xs) is not None: write_pixel(canvas, x, y, color) end = time.time() print("Finished render.") print(str(round(end - start, 2)) + "s") start = time.time() print("Start writing file...") canvas_to_ppm(canvas).write_file("images/circle.ppm") end = time.time() print("Finished writing file.") print(str(round(end - start, 2)) + "s")
def step_impl(context): context.r = ray(point(0, 0.5, -2), vector(0, 0, 1))