def calculateShading(self, intersection, depth): point = intersection[1] shape = intersection[2] normal = shape.getNormalAtPoint(point) incident_vector = (point - self.camera.position).normalized() shapeColor = shape.getColorAtPoint(point) log.debug("Shading {0} {1}".format(shape, point)) # ambient portion result = color.component_scale(shapeColor, [x/255 for x in self.ambient_light]) specular_lights = [] for light in self.lights: # shadow lightDir = (light.position - point).normalized() lightDist = (light.position - point).magnitude() shadowed = False for shape in self.shapes: try: dist, point = shape.intersection(lightDir, point + (normal * 0.001)) if dist <= lightDist: shadowed = True log.debug("Shadowed by {0} at distance {1}".format(shape, dist)) break except TypeError: pass if not shadowed: # diffuse diffIntensity = min(max(lightDir * normal, 0), 1) diff = color.scale(light.color, diffIntensity) diff = color.component_scale(shapeColor, [x/255 for x in diff]) log.debug("Diff: {0} (intensity {1})".format(diff, diffIntensity)) result = color.add(result, diff) if diffIntensity > 0: specular_lights.append(light) # reflection if shape.material.reflection > 0: reflective_vector = incident_vector - (2 * (incident_vector * normal) * normal) reflective_component = self.fireRay(reflective_vector, point + (normal * 0.001), depth + 1) result = color.scale(result, 1 - shape.material.reflection) result = color.add(result, color.scale(reflective_component, shape.material.reflection)) for light in specular_lights: # blinn-phong viewDir = -incident_vector halfDir = (lightDir + viewDir).normalized() specAngle = min(max(halfDir * normal, 0), 1) specIntensity = specAngle ** shape.material.hardness spec = color.scale(light.color, specIntensity) spec = color.scale(spec, shape.material.specular) result = color.add(result, spec) return result
def initScene(): global scene camera = Camera() camera.position = Vector(0, 1, 5) camera.point_at = Vector(0, 1, 0) scene = Scene(window.width, window.height, camera) log.info("Initialized scene with {0}x{1} image, {2}".format(window.width, window.height, camera)) scene.ambient_light = color.scale(color.WHITE, 0.1) light = PointLight() light.position = Vector(5, 8, 8) log.info("Adding {0} to scene".format(light)) scene.lights.append(light) light2 = PointLight() light2.position = Vector(-5, 8, 8) log.info("Adding {0} to scene".format(light2)) scene.lights.append(light2) plane = Plane() plane.material.color = color.scale(color.WHITE, 0.5) plane.material.hardness = 0 plane.material.specular = 0.5 plane.material.reflection = 0.1 log.info("Adding {0} to scene".format(plane)) scene.shapes.append(plane) sphere = Sphere() sphere.position = Vector(1, 2, -3) sphere.radius = 1 sphere.material.color = color.RED sphere.material.specular = 0.5 sphere.material.hardness = 50 sphere.material.reflection = 0.5 log.info("Adding {0} to scene".format(sphere)) scene.shapes.append(sphere) sphere2 = Sphere() sphere2.position = Vector(-1, 1, -1.5) sphere2.radius = 1 sphere2.material.color = color.YELLOW sphere2.material.specular = 0.5 sphere2.material.hardness = 50 sphere2.material.reflection = 0.5 log.info("Adding {0} to scene".format(sphere2)) scene.shapes.append(sphere2)
def add_light(c: Color, l: Light): # print('c=',c) ldis = l.pos - pos livec = ldis.normal() neatIsect = test_ray(Ray(start=pos, dir=livec), scene) isInShadow = False if not neatIsect else neatIsect <= ldis.magnitude() if isInShadow: return c else: illum = livec & norm lcolor = color.default_color if illum < 0 else color.scale(illum, l.color) specular = livec & rd.normal() scolor = color.default_color if specular < 0 else color.scale(specular**thing.surface.roughness, l.color) # print('[types] c:{} pos:{} lcolor:{} scolor:{}'.format(c,pos,lcolor, scolor)) # inter1 = thing.surface.diffuse(pos) # inter2 = thing.surface.specular(pos) # print('[types] inter1:{} inter2:{}'.format(inter1, inter2)) return color.plus(c, (color.times(thing.surface.diffuse(pos) ,lcolor) + color.times(thing.surface.specular(pos), scolor)) )
def __call__(self, time, delta): frame=self.pattern(time, delta) #1. Calculate the total brightness total = 0.0 #cubes for i in range(len(frame[0])): for j in range(len(frame[0][i])): for col in frame[0][i][j]: r, g, b = col total += r+g+b #leaves for i in range(len(frame[1])): for col in frame[1][i]: r, g, b = col total += r+g+b #fissures for col in frame[2]: r, g, b = col total += r+g+b if total > self.max: #scale everything back factor = self.max / total #print('scaling back ',factor) #cubes for i in range(len(frame[0])): for j in range(len(frame[0][i])): for k in range(len(frame[0][i][j])): frame[0][i][j][k] = color.scale(frame[0][i][j][k], factor) #leaves for i in range(len(frame[1])): for j in range(len(frame[1][i])): frame[1][i][j] = color.scale(frame[1][i][j], factor) #fissures for i in range(len(frame[2])): frame[2][i] = color.scale(frame[2][i], factor) return frame
def __init__(self, image_width = 0, image_height = 0, cam = None): self.shapes = [] self.lights = [] if cam is None: self.camera = Camera() else: self.camera = cam self.image_width = image_width self.image_height = image_height self.image_plane = ImagePlane() self.image_plane.setDims(self.camera.fov, self.camera.focal_length, image_width / image_height) self.image_plane.center = self.camera.position - (self.camera.normal() * self.camera.focal_length) self.image_plane.origin = self.image_plane.center - (self.camera.u() * (self.image_plane.width / 2)) - (self.camera.v() * (self.image_plane.height / 2)) self.background_color = color.BLACK self.ambient_light = color.scale(color.WHITE, 0.2) log.info("Scene initialized")
def get_reflection_color(thing: Thing, pos:Vector, normal:Vector, rd:Vector, scene:Scene, depth: int) -> Color: return color.scale(thing.surface.reflect(pos), trace_ray(Ray(start=pos, dir=rd), scene, depth + 1))
def test_scale(self): c1 = Color(0.1, 0.1, 0.1) result = scale(3.0, c1) for n in result: self.assertAlmostEqual(n, 0.3)