def cast_ray(self, orig, direction): material, intersect = self.scene_intersect(orig, direction) if material is None: return self.background_color light_dir = norm(sub(self.light.position, intersect.point)) light_distance = length(sub(self.light.position, intersect.point)) offset_normal = mul(intersect.normal, 1.1) shadow_orig = (sub(intersect.point, offset_normal) if dot(light_dir, intersect.normal) < 0 else sum( intersect.point, offset_normal)) shadow_material, shadow_intersect = self.scene_intersect( shadow_orig, light_dir) shadow_intensity = 0 if (shadow_material and length(sub(shadow_intersect.point, shadow_orig)) < light_distance): shadow_intensity = 0.9 intensity = (self.light.intensity * max(0, dot(light_dir, intersect.normal)) * (1 - shadow_intensity)) reflection = reflect(light_dir, intersect.normal) specular_intensity = self.light.intensity * (max( 0, -dot(reflection, direction))**material.spec) diffuse = material.diffuse * intensity * material.albedo[0] specular = Color(255, 255, 255) * specular_intensity * material.albedo[1] return diffuse + specular
def cast_ray(self, orig, direction, recursion=0): material, intersect = self.scene_intersect(orig, direction) if (material is None or recursion >= MAX_RECURSION_DEPTH): return self.background_color offset_normal = mul(intersect.normal, 1.1) if material.albedo[2] > 0: reverse_direction = mul(direction, -1) reflect_dir = reflect(reverse_direction, intersect.normal) reflect_orig = (sub(intersect.point, offset_normal) if dot(reflect_dir, intersect.normal) < 0 else sum( intersect.point, offset_normal)) reflect_color = self.cast_ray(reflect_orig, reflect_dir, recursion + 1) else: reflect_color = Color(0, 0, 0) if material.albedo[3] > 0: refract_dir = refract(direction, intersect.normal, material.refractive_index) refract_orig = (sub(intersect.point, offset_normal) if dot(refract_dir, intersect.normal) < 0 else sum( intersect.point, offset_normal)) refract_color = self.cast_ray(refract_orig, refract_dir, recursion + 1) else: refract_color = Color(0, 0, 0) light_dir = norm(sub(self.light.position, intersect.point)) light_distance = length(sub(self.light.position, intersect.point)) shadow_orig = (sub(intersect.point, offset_normal) if dot(light_dir, intersect.normal) < 0 else sum( intersect.point, offset_normal)) shadow_material, shadow_intersect = self.scene_intersect( shadow_orig, light_dir) shadow_intensity = 0 if (shadow_material and length(sub(shadow_intersect.point, shadow_orig)) < light_distance): shadow_intensity = 0.9 intensity = (self.light.intensity * max(0, dot(light_dir, intersect.normal)) * (1 - shadow_intensity)) reflection = reflect(light_dir, intersect.normal) specular_intensity = self.light.intensity * (max( 0, -dot(reflection, direction))**material.spec) diffuse = material.diffuse * intensity * material.albedo[0] specular = Color(255, 255, 255) * specular_intensity * material.albedo[1] reflection = reflect_color * material.albedo[2] refraction = refract_color * material.albedo[3] return diffuse + specular + reflection + refraction
def render(self): print("Compilando...") fov = int(pi / 2) for y in range(self.height): for x in range(self.width): i = ((2 * (x + 0.5) / self.width - 1) * tan(fov / 2) * self.width / self.height) j = (2 * (y + 0.5) / self.height - 1) * tan(fov / 2) direction = norm(V3(i, j, -1)) self.pixels[y][x] = self.cast_ray(V3(0, 0, 0), direction)
def ray_intersect(self, orig, direction): L = sub(self.center, orig) tca = dot(L, direction) l = length(L) d2 = l ** 2 - tca ** 2 if d2 > self.radius ** 2: return None thc = (self.radius ** 2 - d2) ** 1 / 2 t0 = tca - thc t1 = tca + thc if t0 < 0: t0 = t1 if t0 < 0: return None hit = sum(orig, mul(direction, t0)) normal = norm(sub(hit, self.center)) return Intersect(distance=t0, point=hit, normal=normal)
def render_stereogram(self): print("Compilando...") fov = int(pi / 2) for y in range(self.height): for x in range(self.width): i = ((2 * (x + 0.5) / self.width - 1) * tan(fov / 2) * self.width / self.height) j = (2 * (y + 0.5) / self.height - 1) * tan(fov / 2) direction = norm(V3(i, j, -1)) first_offset = self.cast_ray(V3(0.25, 0.5, 0), direction) first_camera = ( first_offset / 2 + Color(100, 0, 0) ) if first_offset != self.background_color else first_offset second_offset = self.cast_ray(V3(-0.25, 0.5, 0), direction) second_camera = ( second_offset / 2 + Color(0, 0, 100) ) if second_offset != self.background_color else second_offset camera_offset = first_camera + second_camera self.pixels[y][x] = camera_offset