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 getColor(self, direction): direction = normNPArray(direction) x = int((arctan2(direction[2], direction[0]) / (2 * np.pi) + 0.5) * self.width) y = int(arccos(-direction[1]) / np.pi * self.height) return self.pixels[y][x]
def rtRender(self): #pixel por pixel for y in range(self.height): for x in range(self.width): # pasar valor de pixel a coordenadas NDC (-1 a 1) Px = 2 * ((x + 0.5) / self.width) - 1 Py = 2 * ((y + 0.5) / self.height) - 1 #FOV(angulo de vision), asumiendo que el near plane esta a 1 unidad de la camara t = tan((self.fov * np.pi / 180) / 2) r = t * self.width / self.height Px *= r Py *= t #Nuestra camara siempre esta viendo hacia -Z direction = V3(Px, Py, -1) direction = normNPArray(direction) self.glVertex_coord(x, y, self.castRay(self.camPosition, direction))
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 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)