Пример #1
0
 def __init__(self, diffuseColor=Vector(0.18, 0.18, 0.18), diffuseWeight=1.0,
              reflectionColor=Vector(1, 1, 1), reflectionWeight=0, reflectionRoughness=0,
              refractionColor=Vector(1, 1, 1), refractionWeight=0, refractionIndex=1.5,
              emissionColor=Vector(1, 1, 1), emissionAmount=0):
     # Default material values
     self.diffuseColor = diffuseColor
     self.diffuseWeight = diffuseWeight
     self.reflectionColor = reflectionColor
     self.reflectionWeight = reflectionWeight
     self.reflectionRoughness = reflectionRoughness
     self.refractionColor = refractionColor
     self.refractionWeight = refractionWeight
     self.refractionIndex = refractionIndex
     self.emissionColor = emissionColor
     self.emissionAmount = emissionAmount
Пример #2
0
    def getMirrorReflectionColor(self, currObj, prevHitPos, hitResult,
                                 indirectDepth, reflectDepth, reflectDist):
        reflectionCol = Vector(0, 0, 0)
        reflectDepth += 1
        # If this object's material is perfect mirror, and maybe the reflected ray hits mirror again
        incomingVec = (prevHitPos - hitResult[1]).normalized()
        reflectRayDir = incomingVec.rot("A", math.radians(180), hitResult[2])
        biasedOrigin = hitResult[1] + reflectRayDir * self.bias
        reflectionRay = Ray(biasedOrigin, reflectRayDir)

        reflectHitResult = []
        reflectionHitBool = self.scene.getClosestIntersection(
            reflectionRay, reflectHitResult)

        if reflectionHitBool:
            reflectDist = reflectDist + (
                reflectHitResult[1] - hitResult[1]
            ).length()  # accumulation of distance of reflection
            prevHitPos = hitResult[1]
            hitResult = reflectHitResult
            if reflectDepth < self.reflectionMaxDepth:
                reflectionCol = reflectionCol + self.getColor(
                    hitResult,
                    prevHitPos,
                    indirectDepth=indirectDepth,
                    reflectDepth=reflectDepth,
                    reflectDist=reflectDist).colorMult(
                        currObj.material.reflectionColor)
            else:
                reflectionCol = reflectionCol + self.getHitPointColor(
                    hitResult).colorMult(currObj.material.reflectionColor)

        return reflectionCol
Пример #3
0
    def getHitPointColor(self, hitResult):
        litColor = Vector(0, 0, 0)  #color accumulated after being lit

        #iterate through all the lights using shadow ray, check if object is in shadow
        for eachLight in self.scene.lights:
            for i in range(eachLight.samples):
                if "AreaLight" in eachLight.type:
                    shadowRayDir = eachLight.getRandomSample() - hitResult[1]
                    if eachLight.isDoubleSided == False:
                        #single side area light
                        hitLightBack = shadowRayDir.normalized().dot(
                            eachLight.normal)
                        if hitLightBack > 0:
                            break  #this is a cheat, only works for disk of planeLight
                            #continue
                else:
                    shadowRayDir = eachLight.pos - hitResult[1]

    #lambert is the cosine
                lambert = hitResult[2].dot(shadowRayDir.normalized())
                facingCam = hitResult[2].dot(
                    (self.cam.pos - hitResult[1]).normalized())
                if lambert < 0 and facingCam < 0:
                    #poly is not facing the light or cam
                    lambert = abs(lambert)

                if lambert > 0:
                    #poly is facing the light
                    offsetOrigin = hitResult[1] + shadowRayDir.normalized(
                    ) * self.bias  #slightly offset the ray start point because the origin itself is a root
                    shadowRay = Ray(offsetOrigin, shadowRayDir)
                    temp_t = shadowRayDir.length(
                    )  #length form hit point to light
                    shadowRayResult = [temp_t]
                    inShadow = self.scene.getClosestIntersection(
                        shadowRay, shadowRayResult, eachLight)
                    if not inShadow:
                        litColor = litColor + eachLight.color * (
                            eachLight.intensity * lambert /
                            (4 * math.pi * math.pow(temp_t, 2)))

            litColorAvg = litColor / eachLight.samples * eachLight.area

        matColor = self.scene.getObjectById(hitResult[3]).material.diffuseColor

        return Vector(matColor.x * litColorAvg.x, matColor.y * litColorAvg.y,
                      matColor.z * litColorAvg.z)
Пример #4
0
 def __init__(self,
              pos,
              radius,
              intensity=6,
              color=Vector(1, 1, 1),
              samples=8,
              normal=Vector(0, -1, 0),
              isDoubleSided=False,
              visible=True):
     Disk.__init__(self, pos, radius, normal)
     Light.__init__(self, pos, intensity, color)
     self.type = "AreaLight_Disk"
     self.radius = radius
     self.samples = samples
     self.normal = normal
     self.isDoubleSided = isDoubleSided
     self.visible = visible
     self.area = math.pi * math.pow(radius, 2)
Пример #5
0
 def __init__(self,
              pos,
              radius,
              intensity=10,
              color=Vector(1, 1, 1),
              samples=8):
     super().__init__(pos, intensity, color)
     self.type = "AreaLight_Rectangle"
     self.radius = radius
     self.samples = samples
Пример #6
0
    def getRandomSample(self):
        theta = random.random() * 2 * math.pi  # range [0,2pi)
        u = random.random() + random.random()
        # Better sampling method
        if u > 1:
            multiplier = 2 - u
        else:
            multiplier = u

        return self.pos + Vector(math.cos(theta) * self.radius * multiplier, 0,
                                 math.sin(theta) * self.radius * multiplier)
Пример #7
0
    def getRandomSample(self):
        #generate a sample point on the disk
        # samplePtLi = []
        # for i in range(self.samples):
        theta = random.random() * math.pi  #range [0,2pi)
        multiplier = random.random()  #range [0,1)
        randPointOnDisk = self.pos + Vector(
            math.cos(theta) * self.radius * multiplier, 0,
            math.sin(theta) * self.radius * multiplier)
        #samplePtLi.append(randPointOnDisk)

        return randPointOnDisk
Пример #8
0
    def getRandomPointOnLens(self):
        theta = random.random() * 2 * math.pi  # [0,2pi)
        u = random.random() + random.random()
        # Better sampling method
        if u > 1:
            multiplier = 2 - u
        else:
            multiplier = u

        randPointOnLens = self.pos + Vector(math.cos(theta) * self.pupilDiameter * 0.5 * multiplier,
                                            math.sin(theta) * self.pupilDiameter * 0.5 * multiplier, 0)

        return randPointOnLens
Пример #9
0
	def run(self):
		#bucket rendered color data is stored in an array
		bucketArray = numpy.ndarray(shape=(self.bucketSize,self.bucketSize,3),dtype = numpy.float)
		bucketArray.fill(0) #Very import need to set default color

		#shoot multiple rays each pixel for anti-aliasing
		#--deconstruct self.AAsamples---------
		AAxSubstep = int(math.floor(math.sqrt(self.AAsamples)))
		AAxSubstepLen = 1.0 / AAxSubstep
		AAySubstep = int(self.AAsamples / AAxSubstep)
		AAySubstepLen = 1.0 / AAySubstep

		AAsampleGrid = []
		for AAy in range(0,AAySubstep):
			for AAx in range(0,AAxSubstep):
				AAsingleOffset = [AAx * AAxSubstepLen + AAxSubstepLen/2,AAy * AAySubstepLen + AAySubstepLen/2]
				AAsampleGrid.append(AAsingleOffset)

		timerStart = datetime.now()

		bucketResult = []
		#-------Process keeps getting new bucket-------------------------
		while self.getNextBucket(bucketResult):
			bucketX = bucketResult[0]
			bucketY = bucketResult[1]
			thisAAoffset = bucketResult[2]
			bucketResult.clear()
			#-------------shoot rays---------------------------------------
			#----Each bucket level--------------
			for j in range(bucketY,bucketY + self.bucketSize):
				#----Each line of pixels level--------------
				for i in range(bucketX,bucketX + self.bucketSize):
					#--------Each pixel level--------------------
					col = Vector(0,0,0)
					rayDir = Vector(i + AAsampleGrid[thisAAoffset][0] - self.width/2,
									-j - AAsampleGrid[thisAAoffset][1] + self.height/2,
									-0.5*self.width/math.tan(math.radians(self.cam.angle/2))) #Warning!!!!! Convert to radian!!!!!!!
					camRay = Ray(self.cam.pos,rayDir)

					#hitResult is a list storing calculated data [hit_t, hit_pos,hit_normal,objectId]
					hitResult = []
					hitBool = self.scene.getClosestIntersection(camRay,hitResult)

					if hitBool:
						prevHitPos = self.cam.pos
						col = col + self.getColor(hitResult,prevHitPos)

					bucketArray[j%self.bucketSize,i%self.bucketSize] = [col.x,col.y,col.z]

			returnData = [bucketX,bucketY,bucketArray,thisAAoffset+1,self.AAsamples]
			print("bucket" + str(bucketX) + ":" + str(bucketY) + " Rendered by " + multiprocessing.current_process().name)

			#----get the next bucket--------
			self.outputQ.put(returnData)

		self.outputQ.put("Done")

		timerEnd = datetime.now()
		processRenderTime = timerEnd - timerStart
		print("Process Finished - " + multiprocessing.current_process().name + " Render time: " + str(processRenderTime))
		sys.stdout.flush()
Пример #10
0
	def getColor(self,hitResult,prevHitPos,indirectDepth=0,reflectDepth=0,refractDepth=0,reflectDist=0):
		#Important, when calculating refraction/mirror reflection, pass indirectDepthLimit to getColor to avoid infinite loop
		currObj = self.scene.getObjectById(hitResult[3])
		hitPointColor = Vector(0,0,0)

		if "AreaLight" in currObj.type:
			#if this object is AreaLight, return lightColor * lightIntensity
			if currObj.visible:
				#if hit a light, return color is attenuated. And will be clipped in renderThread
				if indirectDepth == 0:
					#camera ray, no attenuation
					litColor = currObj.color * currObj.intensity
				else:
					#indirect ray, return attenuated value
					litColor = currObj.color * currObj.intensity / (4*math.pi*math.pow(reflectDist,2))

				hitPointColor = hitPointColor + litColor
				return hitPointColor

		if currObj.material.refractionWeight == 1 and currObj.material.reflectionWeight == 1:
			#if this object is glass
			hitPointColor = hitPointColor + self.getRefractionColor(currObj,prevHitPos,hitResult,indirectDepth,refractDepth,reflectDepth,reflectDist)
		elif currObj.material.refractionWeight != 1 and currObj.material.reflectionWeight == 1:
			#If this object is perfect mirror
			hitPointColor = hitPointColor + self.getMirrorReflectionColor(currObj,prevHitPos,hitResult,indirectDepth,reflectDepth,reflectDist)
		else:
			#Diffuse material
			hitPointColor = hitPointColor + self.getHitPointColor(hitResult)

			#Recurvsive path tracing, only for Diffuse material--------------------
			if indirectDepth < self.indirectDepthLimit:
				indirectDepth += 1
				incomingRayDir = hitResult[1] - prevHitPos

				tangentAxis = incomingRayDir.cross(hitResult[2]).normalized()
				biTangentAxis = hitResult[2].cross(tangentAxis).normalized()

				indirectColor = Vector(0,0,0)
				currentObj = self.scene.getObjectById(hitResult[3])

				for i in range(self.indirectSamples):
					tangentRotAmount = random.random()*0.5*math.pi #range: [0,0.5pi)
					biTrangentRotAmount = random.random()*2*math.pi #range: [0,pi)
					indirectRayDir = hitResult[2].rot("A",tangentRotAmount,tangentAxis).rot("A",biTrangentRotAmount,hitResult[2])
					biasedOrigin = hitResult[1] + indirectRayDir * self.bias
					indirectRay = Ray(biasedOrigin,indirectRayDir)

					indirectHitResult = []
					indirectHitBool = self.scene.getClosestIntersection(indirectRay,indirectHitResult)

					if indirectHitBool:
						indirectPointDist = (indirectHitResult[1] - hitResult[1]).length()
						reflectDist = reflectDist + indirectPointDist
						indirectHitPColor = self.getColor(indirectHitResult,hitResult[1],indirectDepth,0,0,reflectDist) #get the indirect color
						lambert = hitResult[2].dot(indirectRayDir)

						indirectLitColor = indirectHitPColor * lambert  #/ (2*math.pi*math.pow(indirectPointDist,2))
						indirectColor = indirectColor + indirectLitColor

				indirectColor = indirectColor / self.indirectSamples * 2 * math.pi
				matColor = currentObj.material.diffuseColor
				hitPointColor = hitPointColor + indirectColor.colorMult(matColor) * 0.3  #arbitrary contribution multiplier

		return hitPointColor
Пример #11
0
	def getRefractionColor(self,currObj,prevHitPos,hitResult,indirectDepth,refractDepth,reflectDepth,reflectDist):
		refractDepth += 1

		refractionCol = Vector(0,0,0)
		reflectionCol = Vector(0,0,0)
		fresnelCol = Vector(0,0,0)
		fresnelRefract = 1
		fresnelReflect = 0

		incomingVec = (prevHitPos - hitResult[1]).normalized() #It's actually the inverse direction of incoming ray
		incomingCos = incomingVec.dot(hitResult[2])
		ior = self.scene.getObjectById(hitResult[3]).material.refractionIndex
		rotAxis = hitResult[2].cross(incomingVec).normalized()

		if incomingCos >= 0 and incomingCos < 1:
			#When ray is entering another medium
			refractAngle = math.asin(math.sqrt(1-math.pow(incomingCos,2))/ior)
			refractRayDir = (hitResult[2]*(-1)).rot("A",refractAngle,rotAxis)
			refractCos = math.cos(refractAngle)
		elif incomingCos > -1 and incomingCos < 0:
			#When ray is leaving the medium
			refractAngleMultIor = math.sqrt(1-math.pow(incomingCos,2))*ior
			if refractAngleMultIor  > 1:
				#Critical angle, total internal reflection
				refractRayDir = incomingVec.rot("A",math.radians(180),hitResult[2])
				refractCos = 0
			else:
				refractAngle = math.asin(refractAngleMultIor)
				refractRayDir = hitResult[2].rot("A",-refractAngle,rotAxis)
				refractCos = math.cos(refractAngle)
		else:
			#incoming ray is perpendicular to the surface
			refractCos = 1
			refractRayDir = incomingVec * (-1)

		biasedOrigin = hitResult[1] + refractRayDir * self.bias
		refractionRay = Ray(biasedOrigin,refractRayDir)
		refractHitResult = []
		refractionHitBool = self.scene.getClosestIntersection(refractionRay,refractHitResult)

		if refractDepth == 1:
			#Calculate fresnel, but only the first refraction
			fresnelS = math.pow((incomingCos - ior*refractCos) / (incomingCos + ior*refractCos),2)
			fresnelP = math.pow((refractCos - ior*incomingCos) / (ior*incomingCos + refractCos),2)
			fresnelReflect = 0.5 * (fresnelS + fresnelP)
			fresnelRefract = 1 - fresnelReflect
			#Get the reflection color
			reflectionCol = reflectionCol + self.getMirrorReflectionColor(currObj,prevHitPos,hitResult,indirectDepth,reflectDepth,reflectDist)

		if refractionHitBool:
			reflectDist = reflectDist + (refractHitResult[1] - hitResult[1]).length() #accumulation of distance of reflection
			prevHitPos = hitResult[1]
			hitResult = refractHitResult
			if refractDepth < self.refractionMaxDepth:
				refractionCol = refractionCol + self.getColor(hitResult,prevHitPos,indirectDepth=indirectDepth,refractDepth=refractDepth,reflectDist=reflectDist)
			else:
				refractionCol = refractionCol + self.getHitPointColor(hitResult)

			fresnelCol = fresnelCol + refractionCol * fresnelRefract + reflectionCol*fresnelReflect

		return fresnelCol
Пример #12
0
 def __init__(self, pos, intensity=5000, color=Vector(1, 1, 1)):
     super().__init__(pos, intensity, color)
     self.type = "Point" + self.type
     self.samples = 1
Пример #13
0
def main():
    renderApp = QApplication(sys.argv)
    renderView = RenderWindow()

    redLambert = Material(diffuseColor=Vector(0.9, 0.1, 0.1))
    blueLambert = Material(diffuseColor=Vector(0, 0, 0.9))
    greenLambert = Material(diffuseColor=Vector(0.1, 0.9, 0.1))
    whiteLambert = Material(diffuseColor=Vector(0.9, 0.9, 0.9))
    yellowLambert = Material(diffuseColor=Vector(0.95, 0.4, 0.0))
    lightBlueLambert = Material(diffuseColor=Vector(0.1, 0.5, 0.9))
    mirror = Material(reflectionColor=Vector(1, 1, 1), reflectionWeight=1)
    redMirror = Material(reflectionColor=Vector(0.9, 0, 0), reflectionWeight=1)
    emissive = Material(emissionAmount=500)
    glass = Material(refractionWeight=1, reflectionWeight=1)

    sphere02 = Sphere(Vector(10, -20, -146), 30, material=mirror)
    sphere03 = Sphere(Vector(-25, -35, -115), 15, material=redMirror)
    sphere04 = Sphere(Vector(25, -35, -100), 15, material=glass)

    plane01 = Plane(Vector(0, -50, -136),
                    Vector(0, 1, 0),
                    material=whiteLambert)  # bottom wall
    plane02 = Plane(Vector(-50, 0, -136),
                    Vector(1, 0, 0),
                    material=yellowLambert)  # left wall
    plane03 = Plane(Vector(0, 0, -186), Vector(0, 0, 1),
                    material=whiteLambert)  # back wall
    plane04 = Plane(Vector(50, 0, -136),
                    Vector(-1, 0, 0),
                    material=lightBlueLambert)  # right wall
    plane05 = Plane(Vector(0, 50, -136), Vector(0, -1, 0),
                    material=emissive)  # top wall

    light01 = DiskLight(Vector(0, 48, -136),
                        30,
                        normal=Vector(0, -1, 0),
                        samples=1,
                        isDoubleSided=True,
                        visible=True)

    newScene = Scene({
        "geometry": [
            plane01, plane02, plane03, plane04, plane05, sphere02, sphere03,
            sphere04
        ],
        "light": [light01]
    })

    teleCam = Camera(Vector(0, 0, 130),
                     Vector(0, 0, 1),
                     80,
                     aperture=1.4,
                     focusDist=243,
                     filmFit="Horizontal")
    renderView.startRender(newScene, teleCam)

    sys.exit(renderApp.exec_())
Пример #14
0
def main():
	renderApp = QApplication(sys.argv)
	renderView = RenderWindow() #All setting loaded from json file

	#--------------------Scene Modeling-------------------------------
	#Materials--------------------------------------------
	redLambert = Material(diffuseColor=Vector(0.9,0.1,0.1))
	blueLambert = Material(diffuseColor=Vector(0,0,0.9))
	greenLambert = Material(diffuseColor=Vector(0.1,0.9,0.1))
	whiteLambert = Material(diffuseColor=Vector(0.9,0.9,0.9))
	mirror = Material(reflectionColor=Vector(1,1,1),reflectionWeight=1)
	redMirror = Material(reflectionColor=Vector(0.9,0,0),reflectionWeight=1)
	emissive = Material(emissionAmount=500)
	glass = Material(refractionWeight=1,reflectionWeight=1)

	#Geometries----------------------------------------------
	#important! This is a right handed coordinate system!
	sphere01 = Sphere(Vector(-15,-30,-136),20,material=whiteLambert)
	sphere02 = Sphere(Vector(10,-20,-146),30,material=mirror)
	sphere03 = Sphere(Vector(-25,-35,-115),15,material=glass)
	sphere04 = Sphere(Vector(25,-35,-100),15,material=whiteLambert)
	#plane01 = Plane(Vector(0,-50,-136),Vector(0,1,0),material=whiteLambert) #bottom wall
	#plane02 = Plane(Vector(-50,0,-136),Vector(1,0,0),material=redLambert) #left wall
	#plane03 = Plane(Vector(0,0,-186),Vector(0,0,1),material=whiteLambert) #back wall
	#plane04 = Plane(Vector(50,0,-136),Vector(-1,0,0),material=greenLambert) #right wall
	#plane05 = Plane(Vector(0,50,-136),Vector(0,-1,0),material=whiteLambert) #top wall
	tri01 = Triangle(Vector(30,40,-136),Vector(-10,20,-136),Vector(50,20,-156),material=glass)
	tri02 = Triangle(Vector(30,40,-146),Vector(50,20,-166),Vector(-10,20,-146),material=glass)
	disk01 = Disk(Vector(-30,30,-136),15,Vector(1,0,0),material=blueLambert)
	quad01 = Quad(Vector(-50,-50,-186),Vector(-50,-50,-76),Vector(50,-50,-76),Vector(50,-50,-186),material=whiteLambert) #bottom wall
	quad02 = Quad(Vector(-50,50,-76),Vector(-50,-50,-76),Vector(-50,-50,-186),Vector(-50,50,-186),material=redLambert) #left wall
	quad03 = Quad(Vector(-50,50,-186),Vector(-50,-50,-186),Vector(50,-50,-186),Vector(50,50,-186),material=whiteLambert)  #back wall
	quad04 = Quad(Vector(50,50,-186),Vector(50,-50,-186),Vector(50,-50,-76),Vector(50,50,-76),material=greenLambert) #right wall
	quad05 = Quad(Vector(-50,50,-76),Vector(-50,50,-186),Vector(50,50,-186),Vector(50,50,-76),material=emissive) #top wall
	quad06 = Quad(Vector(-50,20,-76),Vector(-50,20,-186),Vector(30,20,-186),Vector(30,20,-76),material=whiteLambert) #top matte

	#Lights-------------------------------------------------------
	light01 = DiskLight(Vector(0,48,-136),30,normal=Vector(0,-1,0),samples=8,isDoubleSided=True,visible=True) #light source on the top
	light02 = PointLight(Vector(-20,40,-120))
	light03 = PointLight(Vector(20,30,-90))

	newScene = Scene({"geometry":[quad01,quad02,quad03,quad04,quad05,sphere02,sphere03,sphere04],"light":[light01]})

	cam = Camera(Vector(0,0,0),Vector(0,0,1),60)
	renderView.startRender(newScene,cam)

	sys.exit(renderApp.exec_())