def colorAt(self, objHit, hitPos, hitNormal): material = objHit.material objColor = material.colorAt(hitPos) toCamera = self.camera.subVector(hitPos) specularCoef = 80 color = Color(0,0,0).multiplyVector(material.ambient) for light in self.lights: toTheLight = Ray(hitPos, light.pos.subVector(hitPos)) # Diffuse shading (Lambert) mtrl1 = objColor.multiplyVector(material.diffuse) mtrl2 = mtrl1.multiplyVector(max(hitNormal.dotProduct(toTheLight.direction), 0)) color = color.addVector(mtrl2) # Specular shading (Blinn-Phong) halfVector = (toTheLight.direction.addVector(toCamera)).normalizeVector() mtrl3 = light.color.multiplyVector(material.specular) mtrl4 = mtrl3.multiplyVector(max(hitNormal.dotProduct(halfVector), 0) ** specularCoef) color = color.addVector(mtrl4) return color
def traceRay(self, ray, depth=0, maxDepth= 5): color = Color() # Find the nearest object hit by the ray in the scene distHit, objHit = self.findNearest(ray) if objHit is None: return color hitPos = ray.direction.multiplyVector(distHit).addVector(ray.origin) hitNormal = objHit.surfaceNormal(hitPos) color = color.addVector(self.colorAt(objHit, hitPos, hitNormal)) if depth < maxDepth: #The value of 0.0001 is the minimum displace newRayPos = hitNormal.multiplyVector(0.0001).addVector(hitPos) """Then we implement the reflection formula R = V - 2(V . N) * N where, R is the normalized reflected ray, L is a direction unit vector of the ray to be reflected, N is the direction unit vector normal to the surface the ray stroke """ newRayDirection = ray.direction.subVector(hitNormal.multiplyVector(ray.direction.dotProduct(hitNormal) * 2)) newRay = Ray(newRayPos, newRayDirection) #Attenuation phase color = color.addVector((self.traceRay(newRay, depth+1).multiplyVector(objHit.material.reflection))) return color