def LoadFilm(filmFileName, hasPixelNormalizedChannel, hasScreenNormalizedChannel): fileExt = os.path.splitext(filmFileName)[1] if (fileExt == ".cfg"): # It is a properties file # At least, one of the 2 options must be enabled if (not hasPixelNormalizedChannel) and ( not hasScreenNormalizedChannel): raise TypeError( "At least CHANNEL_RADIANCE_PER_PIXEL_NORMALIZED or CHANNEL_RADIANCE_PER_SCREEN_NORMALIZED must be enabled." "The film would have no content: " + filmFileName) props = pyluxcore.Properties(filmFileName) return pyluxcore.Film(props, hasPixelNormalizedChannel, hasScreenNormalizedChannel) elif (fileExt == ".flm"): # It is a stand alone film return pyluxcore.Film(filmFileName) elif (fileExt == ".rsm"): # It is a resume rendering file (config, startState, startFilm) = pyluxcore.RenderConfig.LoadResumeFile(filmFileName) return startFilm else: raise TypeError("Unknown film file type: " + filmFileName)
def MergeAllFilms(self): # Merge all NodeThreadFilms film = None # Check if I have a previous film to use if self.renderFarmJob.previousFilmFileName: logger.info("Loaded previous film: " + self.renderFarmJob.previousFilmFileName) film = pyluxcore.Film(self.renderFarmJob.previousFilmFileName) stats = film.GetStats() self.previousFilmSampleCount = stats.Get( "stats.film.total.samplecount").GetFloat() else: self.previousFilmSampleCount = 0 logger.info("No previous film to load") # Get a copy of nodeThreads in order to be thread safe nodeThreadsCopy = self.renderFarmJob.GetNodeThreadsList() logger.info("Number of films to merge: " + str(len(nodeThreadsCopy))) for nodeThread in nodeThreadsCopy: with nodeThread.lock: filmThreadFileName = nodeThread.GetNodeFilmFileName() # Check if the file exist if (not os.path.isfile(filmThreadFileName)): logger.info("Film file not yet available: " + nodeThread.thread.name + " (" + filmThreadFileName + ")") continue logger.info("Merging film: " + nodeThread.thread.name + " (" + filmThreadFileName + ")") filmThread = pyluxcore.Film(filmThreadFileName) if filmThread: stats = filmThread.GetStats() spp = stats.Get("stats.film.spp").GetFloat() logger.info(" Samples per pixel: " + "%.1f" % (spp)) if film: # Merge the film film.AddFilm(filmThread) else: # Read the first film film = filmThread return film
def LoadFilm(): print("Film loading...") t1 = Clock() film = pyluxcore.Film("simple.flm") t2 = Clock() print("Film load time: %s secs" % (t2 - t1)) # Define the new image pipeline props = pyluxcore.Properties() props.SetFromString(""" film.imagepipeline.0.type = TONEMAP_LINEAR film.imagepipeline.0.scale = 1.0 film.imagepipeline.1.type = CAMERA_RESPONSE_FUNC film.imagepipeline.1.name = Ektachrome_320TCD film.imagepipeline.2.type = GAMMA_CORRECTION film.imagepipeline.2.value = 2.2 """) film.Parse(props) # Save the tonemapped AOV print("RGB_TONEMAPPED saving...") film.SaveOutput("simple.png", pyluxcore.FilmOutputType.RGB_IMAGEPIPELINE, pyluxcore.Properties()) # Animate radiance groups for i in range(0, 20): props = pyluxcore.Properties() props.SetFromString(""" film.radiancescales.0.globalscale = """ + str(0.025 + (19 - i) * (3.0 / 19.0)) + """ film.radiancescales.1.globalscale = """ + str(0.025 + i * (3.0 / 19.0)) + """ """) film.Parse(props) print("Frame " + str(i) + " saving...") film.SaveOutput("simple" + str(i) + ".png", pyluxcore.FilmOutputType.RGB_IMAGEPIPELINE, pyluxcore.Properties()) print("Film saving...") t1 = Clock() film.SaveFilm("simple2.flm") t2 = Clock() print("Film save time: %s secs" % (t2 - t1)) print("Done.")
def test_Film_SaveLoad(self): # Load the configuration from file props = pyluxcore.Properties("resources/scenes/simple/simple.cfg") # Change the render engine to PATHCPU props.Set(pyluxcore.Property("renderengine.type", ["PATHCPU"])) props.Set(pyluxcore.Property("sampler.type", ["RANDOM"])) props.Set(GetDefaultEngineProperties("PATHCPU")) config = pyluxcore.RenderConfig(props) session = DoRenderSession(config) # Get the imagepipeline result filmA = session.GetFilm() imageA = GetImagePipelineImage(filmA) # Save the film filmA.SaveFilm("simple.flm") # Load the film filmB = pyluxcore.Film("simple.flm") self.assertEqual(filmB.GetWidth(), filmA.GetWidth()) self.assertEqual(filmB.GetHeight(), filmA.GetHeight()) # Get the imagepipeline result imageB = GetImagePipelineImage(filmB) # To debug #imageA.save("imageA.png") #imageB.save("imageB.png") # Check if there is a difference (sameImage, diffCount, diffImage) = CompareImage(imageA, imageB) self.assertTrue(sameImage) os.unlink("simple.flm")
def __init__(self, renderFarm, renderConfigFileName): self.lock = threading.RLock() self.renderFarm = renderFarm self.nodeThreads = list() self.samplesSec = 0.0 self.samplesPixel = 0.0 self.jobUpdateCallBack = None logger.info("New render farm job: " + renderConfigFileName) self.renderConfigFileName = renderConfigFileName # Compute the MD5 of the renderConfigFile self.renderConfigFileMD5 = md5utils.md5sum(renderConfigFileName) logger.info("Job file md5: " + self.renderConfigFileMD5) baseName = os.path.splitext(renderConfigFileName)[0] self.previousFilmFileName = None self.filmFileName = baseName + ".flm" self.imageFileName = baseName + ".png" self.workDirectory = baseName + "-netrendering" self.seed = 1 self.md5FileName = self.workDirectory + "/render.md5" self.seedFileName = self.workDirectory + "/render.seed" # Check the work directory if (os.path.exists(self.workDirectory)): if (not os.path.isdir(self.workDirectory)): raise ValueError("Can not use " + self.workDirectory + " as work directory") else: # The directory already exists, check the md5 of the original scene if self.__CheckWorkDirectoryMD5AndSeed(): # The directory is valid, I can use all films there logger.info("Merging all previous films") # Merge all existing film files in a single one film = None for filmName in [ f for f in os.listdir(self.workDirectory) if f.endswith(".flm") ]: fullFileName = self.workDirectory + "/" + filmName logger.info(" Merging film: " + fullFileName) filmThread = pyluxcore.Film(fullFileName) if filmThread: stats = filmThread.GetStats() spp = stats.Get("stats.film.spp").GetFloat() logger.info(" Samples per pixel: " + "%.1f" % (spp)) if film: # Merge the film film.AddFilm(filmThread) else: # Read the first film film = filmThread # Delete old films for filmName in [ f for f in os.listdir(self.workDirectory) if f.endswith(".flm") ]: filePath = os.path.join(self.workDirectory, filmName) os.unlink(filePath) if film: # TODO add SafeSave self.previousFilmFileName = self.workDirectory + "/previous.flm" film.SaveFilm(self.previousFilmFileName) # Print some film statistics stats = film.GetStats() logger.info("Merged film statistics:") spp = stats.Get("stats.film.spp").GetFloat() logger.info(" Samples per pixel: " + "%.1f" % (spp)) else: # The directory is not valid, erase all the films and the MD5s self.__ClearWorkDirectory() # Write the current MD5 self.__CreateWorkDirectory() else: self.__CreateWorkDirectory() self.filmHaltSPP = 0 self.filmHaltTime = 0 # self.filmHaltConvThreshold = 3.0 / 256.0 self.statsPeriod = 10 self.filmUpdatePeriod = 10 * 60 self.filmMerger = None