def pointColor(self, material, intersect): objectColor = [material.diffuse[2] / 255, material.diffuse[1] / 255, material.diffuse[0] / 255] ambientColor = [0,0,0] diffuseColor = [0,0,0] specColor =[0,0,0] shadow_intensity = 0 if self.ambientLight: ambientColor = [self.ambientLight.strength * self.ambientLight.color[2] / 255, self.ambientLight.strength * self.ambientLight.color[1] / 255, self.ambientLight.strength * self.ambientLight.color[0] / 255] if self.pointLight: # Sacamos la direccion de la luz para este punto light_dir = substractNPArray(self.pointLight.position, intersect.point) light_dir = normNPArray(light_dir) # Calculamos el valor del diffuse color intensity = self.pointLight.intensity * max(0, dotNPArray(light_dir, intersect.normal)) diffuseColor = [intensity * self.pointLight.color[2] / 255, intensity * self.pointLight.color[1] / 255, intensity * self.pointLight.color[2] / 255] # Iluminacion especular view_dir = substractNPArray(self.camPosition, intersect.point) view_dir = normNPArray(view_dir) # R = 2 * (N dot L) * N - L reflect = 2 * dotNPArray(intersect.normal, light_dir) reflect = multiplyConstant(reflect, intersect.normal) reflect = substractNPArray(reflect, light_dir) # spec_intensity: lightIntensity * ( view_dir dot reflect) ** specularidad spec_intensity = self.pointLight.intensity * (max(0, dotNPArray(view_dir, reflect)) ** material.spec) specColor = [spec_intensity * self.pointLight.color[2] / 255, spec_intensity * self.pointLight.color[1] / 255, spec_intensity * self.pointLight.color[0] / 255] for obj in self.scene: if obj is not intersect.sceneObject: hit = obj.ray_intersect(intersect.point, light_dir) if hit is not None and intersect.distance < np.linalg.norm(substractNPArray(self.pointLight.position, intersect.point)): shadow_intensity = 1 # Formula de iluminacion # finalColor = (ambientColor + (1 - shadow_intensity) * (diffuseColor + specColor)) * objectColor finalColor = multiplyColor(sumNPArray(ambientColor, multiplyConstant((1 - shadow_intensity),sumNPArray(diffuseColor, specColor))),objectColor) #Nos aseguramos que no suba el valor de color de 1 r = min(1,finalColor[0]) g = min(1,finalColor[1]) b = min(1,finalColor[2]) return color(r, g, b)
def reflectVector(normal, dirVector): # R = 2 * (N dot L) * N - L reflect = 2 * dotNPArray(normal, dirVector) reflect = multiplyConstant(reflect, normal) reflect = substractNPArray(reflect, dirVector) reflect = normNPArray(reflect) return reflect
def ray_intersect(self, orig, dir): # t = (( position - origRayo) dot normal) / (dirRayo dot normal) denom = dotNPArray(dir, self.normal) if abs(denom) > 0.0001: t = dotNPArray(self.normal, substractNPArray(self.position, orig)) / denom if t > 0: # P = O + tD hit = sumNPArray(orig, t * np.array(dir)) return Intersect(distance=t, point=hit, normal=self.normal, sceneObject=self) return None
def fresnel(N, I, ior): # N = normal # I = incident vector # ior = index of refraction cosi = max(-1, min(1, dotNPArray(I, N))) etai = 1 etat = ior if cosi > 0: etai, etat = etat, etai sint = etai / etat * (max(0, 1 - cosi * cosi)**0.5) if sint >= 1: # Total Internal Reflection return 1 cost = max(0, 1 - sint * sint)**0.5 cosi = abs(cosi) Rs = ((etat * cosi) - (etai * cost)) / ((etat * cosi) + (etai * cost)) Rp = ((etai * cosi) - (etat * cost)) / ((etai * cosi) + (etat * cost)) return (Rs * Rs + Rp * Rp) / 2
def refractVector(N, I, ior): # N = normal # I = incident vector # ior = index of refraction # Snell's Law cosi = max(-1, min(1, dotNPArray(I, N))) etai = 1 etat = ior if cosi < 0: cosi = -cosi else: etai, etat = etat, etai N = np.array(N) * -1 eta = etai / etat k = 1 - eta * eta * (1 - (cosi * cosi)) if k < 0: # Total Internal Reflection return None R = eta * np.array(I) + (eta * cosi - k**0.5) * N return normNPArray(R)
def ray_intersect(self, orig, dir): L = substractNPArray(self.center, orig) tca = dotNPArray(L, dir) l = magnitudeNpArray(L) # magnitud de L d = (l**2 - tca**2)**0.5 if d > self.radius: return None # thc es la distancia de P1 al punto perpendicular al centro thc = (self.radius**2 - d**2)**0.5 t0 = tca - thc t1 = tca + thc if t0 < 0: t0 = t1 if t0 < 0: # t0 tiene el valor de t1 return None # P = O + tD hit = sumNPArray(orig, t0 * np.array(dir)) norm = substractNPArray(hit, self.center) norm = norm / np.linalg.norm(norm) return Intersect(distance=t0, point=hit, normal=norm, sceneObject=self)
def castRay(self, orig, direction, origObj=None, recursion=0): material, intersect = self.scene_intercept(orig, direction, origObj) if material is None or recursion >= MAX_RECURSION_DEPTH: if self.envmap: return self.envmap.getColor(direction) return self.clear_color objectColor = np.array([ material.diffuse[2] / 255, material.diffuse[1] / 255, material.diffuse[0] / 255 ]) ambientColor = np.array([0, 0, 0]) diffuseColor = np.array([0, 0, 0]) specColor = np.array([0, 0, 0]) reflectColor = np.array([0, 0, 0]) refractColor = np.array([0, 0, 0]) finalColor = np.array([0, 0, 0]) shadow_intensity = 0 # Direccion de vista view_dir = substractNPArray(self.camPosition, intersect.point) view_dir = normNPArray(view_dir) if self.ambientLight: ambientColor = np.array([ self.ambientLight.strength * self.ambientLight.color[2] / 255, self.ambientLight.strength * self.ambientLight.color[1] / 255, self.ambientLight.strength * self.ambientLight.color[0] / 255 ]) if self.pointLight: # Sacamos la direccion de la luz para este punto light_dir = substractNPArray(self.pointLight.position, intersect.point) light_dir = normNPArray(light_dir) # Calculamos el valor del diffuse color intensity = self.pointLight.intensity * max( 0, dotNPArray(light_dir, intersect.normal)) diffuseColor = np.array([ intensity * self.pointLight.color[2] / 255, intensity * self.pointLight.color[1] / 255, intensity * self.pointLight.color[2] / 255 ]) # Iluminacion especular reflect = reflectVector(intersect.normal, light_dir) # Reflejar el vector de luz # spec_intensity: lightIntensity * ( view_dir dot reflect) ** especularidad spec_intensity = self.pointLight.intensity * (max( 0, dotNPArray(view_dir, reflect))**material.spec) specColor = np.array([ spec_intensity * self.pointLight.color[2] / 255, spec_intensity * self.pointLight.color[1] / 255, spec_intensity * self.pointLight.color[0] / 255 ]) shadMat, shadInter = self.scene_intercept(intersect.point, light_dir, intersect.sceneObject) if shadInter is not None and shadInter.distance < magnitudeNpArray( substractNPArray(self.pointLight.position, intersect.point)): shadow_intensity = 1 if material.matType == OPAQUE: # Formula de iluminacion, PHONG finalColor = (ambientColor + (1 - shadow_intensity) * (diffuseColor + specColor)) elif material.matType == REFLECTIVE: reflect = reflectVector(intersect.normal, np.array(direction) * -1) reflectColor = self.castRay(intersect.point, reflect, intersect.sceneObject, recursion + 1) reflectColor = np.array([ reflectColor[2] / 255, reflectColor[1] / 255, reflectColor[0] / 255 ]) finalColor = reflectColor + (1 - shadow_intensity) * specColor elif material.matType == TRANSPARENT: outside = dotNPArray(direction, intersect.normal) < 0 bias = 0.001 * intersect.normal kr = fresnel(intersect.normal, direction, material.ior) reflect = reflectVector(intersect.normal, np.array(direction) * -1) reflectOrig = sumNPArray(intersect.point, bias) if outside else substractNPArray( intersect.point, bias) reflectColor = self.castRay(reflectOrig, reflect, None, recursion + 1) reflectColor = np.array([ reflectColor[2] / 255, reflectColor[1] / 255, reflectColor[0] / 255 ]) if kr < 1: refract = refractVector(intersect.normal, direction, material.ior) refractOrig = substractNPArray( intersect.point, bias) if outside else sumNPArray( intersect.point, bias) refractColor = self.castRay(refractOrig, refract, None, recursion + 1) refractColor = np.array([ refractColor[2] / 255, refractColor[1] / 255, refractColor[0] / 255 ]) finalColor = reflectColor * kr + refractColor * (1 - kr) + ( 1 - shadow_intensity) * specColor # Le aplicamos el color del objeto finalColor *= objectColor #Nos aseguramos que no suba el valor de color de 1 r = min(1, finalColor[0]) g = min(1, finalColor[1]) b = min(1, finalColor[2]) return color(r, g, b)