def init(self): """ Initializes the vertex buffers and makes them available as shader inputs. """ self.vertexBuffers = [] for i in xrange(2): vertexBuffer = Texture("VertexPositionBuffer-" + str(i)) vertexBuffer.setup2dTexture(self.split, self.maxVertexCount / self.split, Texture.TFloat, Texture.FRgba32) vertexBuffer.setClearColor(Vec4(0)) vertexBuffer.clearImage() MemoryMonitor.addTexture("DynamicObjectVtxBuffer" + str(i), vertexBuffer) Globals.render.setShaderInput("dynamicObjectVtxBuffer" + str(i), vertexBuffer) BufferViewerGUI.registerTexture("Vtx Positions " + str(i), vertexBuffer) vertexBuffer.setWrapU(Texture.WMClamp) vertexBuffer.setWrapV(Texture.WMClamp) vertexBuffer.setMinfilter(Texture.FTNearest) vertexBuffer.setMagfilter(Texture.FTNearest) self.vertexBuffers.append(vertexBuffer) Globals.render.setShaderInput("dynamicVtxSplit", self.split)
def create(self): """ Creates the passes """ self.cloudStartHeight = 900.0 self.cloudEndHeight = 3300.0 self.cloudResolution = 768 self.cloudResolutionH = 128 self.voxelGrid = Texture("CloudVoxelGrid") self.voxelGrid.setup3dTexture(self.cloudResolution, self.cloudResolution, self.cloudResolutionH, Texture.TFloat, Texture.FR16) self.voxelGrid.setWrapU(Texture.WMRepeat) self.voxelGrid.setWrapV(Texture.WMRepeat) self.voxelGrid.setWrapW(Texture.WMClamp) self.cloudNoise = Texture("CloudNoise") self.cloudNoise.setup3dTexture(64, 64, 64, Texture.TFloat, Texture.FR16) self.cloudNoise.setWrapU(Texture.WMRepeat) self.cloudNoise.setWrapV(Texture.WMRepeat) self.cloudNoise.setWrapW(Texture.WMRepeat) MemoryMonitor.addTexture("CloudVoxelGrid", self.voxelGrid) MemoryMonitor.addTexture("CloudNoise", self.cloudNoise) self._createInitialGrid() self.renderPass = CloudRenderPass() self.pipeline.getRenderPassManager().registerPass(self.renderPass) self.pipeline.getRenderPassManager().registerStaticVariable("cloudVoxelGrid", self.voxelGrid) self.pipeline.getRenderPassManager().registerStaticVariable("cloudStartHeight", self.cloudStartHeight) self.pipeline.getRenderPassManager().registerStaticVariable("cloudEndHeight", self.cloudEndHeight) self.pipeline.getRenderPassManager().registerStaticVariable("cloudNoise", self.cloudNoise) self.pipeline.getRenderPassManager().registerDefine("CLOUDS_ENABLED", 1)
def create(self): """ Creates the passes required to compute the occlusion, selecting the appropriate pass for the selected technique """ technique = self.pipeline.settings.occlusionTechnique if technique not in self.availableTechniques: self.error("Unrecognized technique: " + technique) return if technique == "None": return # Create the ambient occlusion pass. The technique is selected in the # shader later, based on the defines self.aoPass = AmbientOcclusionPass() self.pipeline.getRenderPassManager().registerPass(self.aoPass) # Create the ambient occlusion blur pass self.blurPass = OcclusionBlurPass() self.pipeline.getRenderPassManager().registerPass(self.blurPass) # Register the configuration defines self.pipeline.getRenderPassManager().registerDefine( "OCCLUSION_TECHNIQUE_" + technique, 1) self.pipeline.getRenderPassManager().registerDefine("USE_OCCLUSION", 1) self.pipeline.getRenderPassManager().registerDefine( "OCCLUSION_RADIUS", self.pipeline.settings.occlusionRadius) self.pipeline.getRenderPassManager().registerDefine( "OCCLUSION_STRENGTH", self.pipeline.settings.occlusionStrength) self.pipeline.getRenderPassManager().registerDefine( "OCCLUSION_SAMPLES", self.pipeline.settings.occlusionSampleCount) if self.pipeline.settings.useLowQualityBlur: self.pipeline.getRenderPassManager().registerDefine( "USE_LOW_QUALITY_BLUR", 1) if self.pipeline.settings.useOcclusionNoise: self.pipeline.getRenderPassManager().registerDefine( "USE_OCCLUSION_NOISE", 1) if self.pipeline.settings.useTemporalOcclusion: # Create a texture to store the last frame occlusion self.lastFrameOcclusionTex = Texture("LastFrameOcclusion") self.lastFrameOcclusionTex.setup2dTexture(Globals.resolution.x, Globals.resolution.y, Texture.TFloat, Texture.FR16) self.pipeline.getRenderPassManager().registerStaticVariable( "lastFrameOcclusion", self.lastFrameOcclusionTex) BufferViewerGUI.registerTexture("LastFrameOcclusion", self.lastFrameOcclusionTex) MemoryMonitor.addTexture("LastFrameOcclusion", self.lastFrameOcclusionTex) self.pipeline.getRenderPassManager().registerDefine( "USE_TEMPORAL_OCCLUSION", 1) self.combinePass = OcclusionCombinePass() self.pipeline.getRenderPassManager().registerPass(self.combinePass)
def _createLastFrameBuffers(self): """ Creates the buffers which store the last frame depth, as the render target matcher cannot handle this """ self.lastFrameDepth = Texture("LastFrameDepth") self.lastFrameDepth.setup2dTexture(Globals.resolution.x, Globals.resolution.y, Texture.TFloat, Texture.FR32) BufferViewerGUI.registerTexture("LastFrameDepth", self.lastFrameDepth) MemoryMonitor.addTexture("LastFrameDepth", self.lastFrameDepth) self.renderPassManager.registerStaticVariable("lastFrameDepth", self.lastFrameDepth)
def create(self): """ Creates the passes required to compute the occlusion, selecting the appropriate pass for the selected technique """ technique = self.pipeline.settings.occlusionTechnique if technique not in self.availableTechniques: self.error("Unrecognized technique: " + technique) return if technique == "None": return # Create the ambient occlusion pass. The technique is selected in the # shader later, based on the defines self.aoPass = AmbientOcclusionPass() self.pipeline.getRenderPassManager().registerPass(self.aoPass) # Create the ambient occlusion blur pass self.blurPass = OcclusionBlurPass() self.pipeline.getRenderPassManager().registerPass(self.blurPass) # Register the configuration defines self.pipeline.getRenderPassManager().registerDefine("OCCLUSION_TECHNIQUE_" + technique, 1) self.pipeline.getRenderPassManager().registerDefine("USE_OCCLUSION", 1) self.pipeline.getRenderPassManager().registerDefine("OCCLUSION_RADIUS", self.pipeline.settings.occlusionRadius) self.pipeline.getRenderPassManager().registerDefine("OCCLUSION_STRENGTH", self.pipeline.settings.occlusionStrength) self.pipeline.getRenderPassManager().registerDefine("OCCLUSION_SAMPLES", self.pipeline.settings.occlusionSampleCount) if self.pipeline.settings.useLowQualityBlur: self.pipeline.getRenderPassManager().registerDefine("USE_LOW_QUALITY_BLUR", 1) if self.pipeline.settings.useOcclusionNoise: self.pipeline.getRenderPassManager().registerDefine("USE_OCCLUSION_NOISE", 1) if self.pipeline.settings.useTemporalOcclusion: # Create a texture to store the last frame occlusion self.lastFrameOcclusionTex = Texture("LastFrameOcclusion") self.lastFrameOcclusionTex.setup2dTexture(Globals.base.win.getXSize(), Globals.base.win.getYSize(), Texture.TFloat, Texture.FR16) self.pipeline.getRenderPassManager().registerStaticVariable("lastFrameOcclusion", self.lastFrameOcclusionTex) BufferViewerGUI.registerTexture("LastFrameOcclusion", self.lastFrameOcclusionTex) MemoryMonitor.addTexture("LastFrameOcclusion", self.lastFrameOcclusionTex) self.pipeline.getRenderPassManager().registerDefine("USE_TEMPORAL_OCCLUSION", 1) self.combinePass = OcclusionCombinePass() self.pipeline.getRenderPassManager().registerPass(self.combinePass)
def initTransparencyPass(self): """ Creates the pass which renders the transparent objects into the scene """ self.transparencyPass = TransparencyPass() self.pipeline.getRenderPassManager().registerPass(self.transparencyPass) # Create the atomic counter which stores the amount of rendered transparent # pixels. For now this a 1x1 texture, as atomic counters are not implemented. self.pixelCountBuffer = Texture("MaterialCountBuffer") self.pixelCountBuffer.setup2dTexture(1, 1, Texture.TInt, Texture.FR32i) # Creates the buffer which stores all transparent pixels. Pixels are inserted # into the buffer in the order they are rendered, using the pixelCountBuffer # to determine their index self.materialDataBuffer = Texture("MaterialDataBuffer") self.materialDataBuffer.setupBufferTexture(self.maxPixelCount, Texture.TFloat, Texture.FRgba32, GeomEnums.UH_static) # Creates the list head buffer, which stores the first transparent pixel for # each window pixel. The index stored in this buffer is the index into the # materialDataBuffer self.listHeadBuffer = Texture("ListHeadBuffer") self.listHeadBuffer.setup2dTexture(self.pipeline.getSize().x, self.pipeline.getSize().y, Texture.TInt, Texture.FR32i) # Creates the spinlock buffer, which ensures that writing to the listHeadBuffer # is sequentially self.spinLockBuffer = Texture("SpinLockBuffer") self.spinLockBuffer.setup2dTexture(self.pipeline.getSize().x, self.pipeline.getSize().y, Texture.TInt, Texture.FR32i) # Set the buffers as input to the main scene. Maybe we can do this more elegant target = self.pipeline.showbase.render target.setShaderInput("pixelCountBuffer", self.pixelCountBuffer) target.setShaderInput("spinLockBuffer", self.spinLockBuffer) target.setShaderInput("materialDataBuffer", self.materialDataBuffer) target.setShaderInput("listHeadBuffer", self.listHeadBuffer) # Provides the buffers as global shader inputs self.pipeline.getRenderPassManager().registerStaticVariable("transpPixelCountBuffer", self.pixelCountBuffer) self.pipeline.getRenderPassManager().registerStaticVariable("transpSpinLockBuffer", self.spinLockBuffer) self.pipeline.getRenderPassManager().registerStaticVariable("transpListHeadBuffer", self.listHeadBuffer) self.pipeline.getRenderPassManager().registerStaticVariable("transpMaterialDataBuffer", self.materialDataBuffer) # Registers the transparency settings to the shaders self.pipeline.getRenderPassManager().registerDefine("USE_TRANSPARENCY", 1) self.pipeline.getRenderPassManager().registerDefine("MAX_TRANSPARENCY_LAYERS", self.pipeline.settings.maxTransparencyLayers) self.pixelCountBuffer.setClearColor(Vec4(0, 0, 0, 0)) self.spinLockBuffer.setClearColor(Vec4(0, 0, 0, 0)) self.listHeadBuffer.setClearColor(Vec4(0, 0, 0, 0)) MemoryMonitor.addTexture("MaterialCountBuffer", self.pixelCountBuffer) MemoryMonitor.addTexture("MaterialDataBuffer", self.materialDataBuffer) MemoryMonitor.addTexture("ListHeadBuffer", self.listHeadBuffer) MemoryMonitor.addTexture("SpinLockBuffer", self.spinLockBuffer)
def _makeRenderedLightsBuffer(self): """ Creates the buffer which stores the indices of all rendered lights """ bufferSize = 16 bufferSize += LightLimits.maxLights["PointLight"] bufferSize += LightLimits.maxLights["PointLightShadow"] bufferSize += LightLimits.maxLights["DirectionalLight"] bufferSize += LightLimits.maxLights["DirectionalLightShadow"] bufferSize += LightLimits.maxLights["SpotLight"] bufferSize += LightLimits.maxLights["SpotLightShadow"] self.renderedLightsBuffer = Texture("RenderedLightsBuffer") self.renderedLightsBuffer.setupBufferTexture(bufferSize, Texture.TInt, Texture.FR32i, GeomEnums.UHDynamic) self.pipeline.getRenderPassManager().registerStaticVariable( "renderedLightsBuffer", self.renderedLightsBuffer) MemoryMonitor.addTexture("Rendered Lights Buffer", self.renderedLightsBuffer)
def create(self): """ Creates the passes """ self.cloudStartHeight = 900.0 self.cloudEndHeight = 3300.0 self.cloudResolution = 768 self.cloudResolutionH = 128 self.voxelGrid = Texture("CloudVoxelGrid") self.voxelGrid.setup3dTexture(self.cloudResolution, self.cloudResolution, self.cloudResolutionH, Texture.TFloat, Texture.FR16) self.voxelGrid.setWrapU(Texture.WMRepeat) self.voxelGrid.setWrapV(Texture.WMRepeat) self.voxelGrid.setWrapW(Texture.WMClamp) self.cloudNoise = Texture("CloudNoise") self.cloudNoise.setup3dTexture(64, 64, 64, Texture.TFloat, Texture.FR16) self.cloudNoise.setWrapU(Texture.WMRepeat) self.cloudNoise.setWrapV(Texture.WMRepeat) self.cloudNoise.setWrapW(Texture.WMRepeat) MemoryMonitor.addTexture("CloudVoxelGrid", self.voxelGrid) MemoryMonitor.addTexture("CloudNoise", self.cloudNoise) self._createInitialGrid() self.renderPass = CloudRenderPass() self.pipeline.getRenderPassManager().registerPass(self.renderPass) self.pipeline.getRenderPassManager().registerStaticVariable( "cloudVoxelGrid", self.voxelGrid) self.pipeline.getRenderPassManager().registerStaticVariable( "cloudStartHeight", self.cloudStartHeight) self.pipeline.getRenderPassManager().registerStaticVariable( "cloudEndHeight", self.cloudEndHeight) self.pipeline.getRenderPassManager().registerStaticVariable( "cloudNoise", self.cloudNoise) self.pipeline.getRenderPassManager().registerDefine( "CLOUDS_ENABLED", 1)
def init(self): """ Initializes the vertex buffers and makes them available as shader inputs. """ self.vertexBuffers = [] for i in xrange(2): vertexBuffer = Texture("VertexPositionBuffer-" + str(i)) vertexBuffer.setup2dTexture(self.split, self.maxVertexCount / self.split, Texture.TFloat, Texture.FRgba32) vertexBuffer.setClearColor(Vec4(0)) vertexBuffer.clearImage() MemoryMonitor.addTexture("DynamicObjectVtxBuffer"+str(i), vertexBuffer) Globals.render.setShaderInput("dynamicObjectVtxBuffer"+str(i), vertexBuffer) BufferViewerGUI.registerTexture("Vtx Positions " + str(i), vertexBuffer) vertexBuffer.setWrapU(Texture.WMClamp) vertexBuffer.setWrapV(Texture.WMClamp) vertexBuffer.setMinfilter(Texture.FTNearest) vertexBuffer.setMagfilter(Texture.FTNearest) self.vertexBuffers.append(vertexBuffer) Globals.render.setShaderInput("dynamicVtxSplit", self.split)
def setup(self): """ Setups everything for the GI to work """ assert (self.distributionSteps % 2 == 0) self._createDebugTexts() self.pipeline.getRenderPassManager().registerDefine( "USE_GLOBAL_ILLUMINATION", 1) self.pipeline.getRenderPassManager().registerDefine( "GI_SLIDE_COUNT", self.slideCount) self.pipeline.getRenderPassManager().registerDefine( "GI_QUALITY_LEVEL", self.qualityLevelIndex) # make the grid resolution a constant self.pipeline.getRenderPassManager().registerDefine( "GI_GRID_RESOLUTION", self.voxelGridResolution) self.taskManager.addTask(3, self.stepVoxelize) self.taskManager.addTask(self.distributionSteps, self.stepDistribute) # Create the voxelize pass which is used to voxelize the scene from # several directions self.voxelizePass = VoxelizePass(self.pipeline) self.voxelizePass.setVoxelGridResolution(self.voxelGridResolution) self.voxelizePass.setVoxelGridSize(self.voxelGridSize) self.voxelizePass.setGridResolutionMultiplier(1) self.pipeline.getRenderPassManager().registerPass(self.voxelizePass) self.generationTextures = [] # Create the buffers used to create the voxel grid for color in "rgb": tex = Texture("VoxelGeneration-" + color) tex.setup3dTexture(self.voxelGridResolution, self.voxelGridResolution, self.voxelGridResolution, Texture.TInt, Texture.FR32) tex.setClearColor(Vec4(0)) self.generationTextures.append(tex) Globals.render.setShaderInput("voxelGenDest" + color.upper(), tex) MemoryMonitor.addTexture("VoxelGenerationTex-" + color.upper(), tex) self.bindTo(Globals.render, "giData") self.convertGridTarget = RenderTarget("ConvertGIGrid") self.convertGridTarget.setSize( self.voxelGridResolution * self.slideCount, self.voxelGridResolution * self.slideVertCount) if self.pipeline.settings.useDebugAttachments: self.convertGridTarget.addColorTexture() self.convertGridTarget.prepareOffscreenBuffer() # Set a near-filter to the texture if self.pipeline.settings.useDebugAttachments: self.convertGridTarget.getColorTexture().setMinfilter( Texture.FTNearest) self.convertGridTarget.getColorTexture().setMagfilter( Texture.FTNearest) self.clearGridTarget = RenderTarget("ClearGIGrid") self.clearGridTarget.setSize( self.voxelGridResolution * self.slideCount, self.voxelGridResolution * self.slideVertCount) if self.pipeline.settings.useDebugAttachments: self.clearGridTarget.addColorTexture() self.clearGridTarget.prepareOffscreenBuffer() for idx, color in enumerate("rgb"): self.convertGridTarget.setShaderInput( "voxelGenSrc" + color.upper(), self.generationTextures[idx]) self.clearGridTarget.setShaderInput("voxelGenTex" + color.upper(), self.generationTextures[idx]) # Create the data textures self.dataTextures = [] self.directions = ["PosX", "NegX", "PosY", "NegY", "PosZ", "NegZ"] for i, direction in enumerate(self.directions): tex = Texture("GIDataTex" + direction) tex.setup3dTexture(self.voxelGridResolution, self.voxelGridResolution, self.voxelGridResolution, Texture.TFloat, Texture.FR11G11B10) MemoryMonitor.addTexture("VoxelDataTex-" + direction, tex) self.dataTextures.append(tex) self.pipeline.getRenderPassManager().registerStaticVariable( "giVoxelData" + direction, tex) # Create ping / pong textures self.pingDataTextures = [] self.pongDataTextures = [] for i, direction in enumerate(self.directions): texPing = Texture("GIPingDataTex" + direction) texPing.setup3dTexture(self.voxelGridResolution, self.voxelGridResolution, self.voxelGridResolution, Texture.TFloat, Texture.FR11G11B10) MemoryMonitor.addTexture("VoxelPingDataTex-" + direction, texPing) self.pingDataTextures.append(texPing) texPong = Texture("GIPongDataTex" + direction) texPong.setup3dTexture(self.voxelGridResolution, self.voxelGridResolution, self.voxelGridResolution, Texture.TFloat, Texture.FR11G11B10) MemoryMonitor.addTexture("VoxelPongDataTex-" + direction, texPong) self.pongDataTextures.append(texPong) self.convertGridTarget.setShaderInput("voxelDataDest" + direction, self.pingDataTextures[i]) # self.clearGridTarget.setShaderInput("voxelDataDest" + str(i), self.pongDataTextures[i]) # Set texture wrap modes for tex in self.pingDataTextures + self.pongDataTextures + self.dataTextures + self.generationTextures: tex.setMinfilter(Texture.FTLinear) tex.setMagfilter(Texture.FTLinear) tex.setWrapU(Texture.WMBorderColor) tex.setWrapV(Texture.WMBorderColor) tex.setWrapW(Texture.WMBorderColor) tex.setAnisotropicDegree(0) tex.setBorderColor(Vec4(0)) for tex in self.dataTextures: tex.setMinfilter(Texture.FTLinear) tex.setMagfilter(Texture.FTLinear) self.distributeTarget = RenderTarget("DistributeVoxels") self.distributeTarget.setSize( self.voxelGridResolution * self.slideCount, self.voxelGridResolution * self.slideVertCount) if self.pipeline.settings.useDebugAttachments: self.distributeTarget.addColorTexture() self.distributeTarget.prepareOffscreenBuffer() # Set a near-filter to the texture if self.pipeline.settings.useDebugAttachments: self.distributeTarget.getColorTexture().setMinfilter( Texture.FTNearest) self.distributeTarget.getColorTexture().setMagfilter( Texture.FTNearest) self.distributeTarget.setShaderInput("isLastStep", False) # Create solidness texture self.voxelSolidTex = Texture("GIDataSolidTex") self.voxelSolidTex.setup3dTexture(self.voxelGridResolution, self.voxelGridResolution, self.voxelGridResolution, Texture.TFloat, Texture.FR16) self.convertGridTarget.setShaderInput("voxelSolidDest", self.voxelSolidTex) self.distributeTarget.setShaderInput("voxelSolidTex", self.voxelSolidTex) MemoryMonitor.addTexture("VoxelSolidTex", self.voxelSolidTex) self.voxelSolidStableTex = Texture("GIDataSolidStableTex") self.voxelSolidStableTex.setup3dTexture(self.voxelGridResolution, self.voxelGridResolution, self.voxelGridResolution, Texture.TFloat, Texture.FR16) self.distributeTarget.setShaderInput("voxelSolidWriteTex", self.voxelSolidStableTex) self.pipeline.getRenderPassManager().registerStaticVariable( "giVoxelSolidTex", self.voxelSolidStableTex) # Create the final gi pass self.finalPass = GlobalIlluminationPass() self.pipeline.getRenderPassManager().registerPass(self.finalPass) self.pipeline.getRenderPassManager().registerDynamicVariable( "giData", self.bindTo) self.pipeline.getRenderPassManager().registerStaticVariable( "giReadyState", self.readyStateFlag) # Visualize voxels if False: self.voxelCube = loader.loadModel("Box") self.voxelCube.reparentTo(render) # self.voxelCube.setTwoSided(True) self.voxelCube.node().setFinal(True) self.voxelCube.node().setBounds(OmniBoundingVolume()) self.voxelCube.setInstanceCount(self.voxelGridResolution**3) # self.voxelCube.hide() self.bindTo(self.voxelCube, "giData") for i in xrange(5): self.voxelCube.setShaderInput("giDataTex" + str(i), self.pingDataTextures[i]) self.disableTargets()
def setup(self): """ Setups everything for the GI to work """ assert(self.distributionSteps % 2 == 0) self._createDebugTexts() self.pipeline.getRenderPassManager().registerDefine("USE_GLOBAL_ILLUMINATION", 1) self.pipeline.getRenderPassManager().registerDefine("GI_SLIDE_COUNT", self.slideCount) self.pipeline.getRenderPassManager().registerDefine("GI_QUALITY_LEVEL", self.qualityLevelIndex) # make the grid resolution a constant self.pipeline.getRenderPassManager().registerDefine("GI_GRID_RESOLUTION", self.voxelGridResolution) self.taskManager.addTask(3, self.stepVoxelize) self.taskManager.addTask(self.distributionSteps, self.stepDistribute) # Create the voxelize pass which is used to voxelize the scene from # several directions self.voxelizePass = VoxelizePass(self.pipeline) self.voxelizePass.setVoxelGridResolution(self.voxelGridResolution) self.voxelizePass.setVoxelGridSize(self.voxelGridSize) self.voxelizePass.setGridResolutionMultiplier(1) self.pipeline.getRenderPassManager().registerPass(self.voxelizePass) self.generationTextures = [] # Create the buffers used to create the voxel grid for color in "rgb": tex = Texture("VoxelGeneration-" + color) tex.setup3dTexture(self.voxelGridResolution, self.voxelGridResolution, self.voxelGridResolution, Texture.TInt, Texture.FR32) tex.setClearColor(Vec4(0)) self.generationTextures.append(tex) Globals.render.setShaderInput("voxelGenDest" + color.upper(), tex) MemoryMonitor.addTexture("VoxelGenerationTex-" + color.upper(), tex) self.bindTo(Globals.render, "giData") self.convertGridTarget = RenderTarget("ConvertGIGrid") self.convertGridTarget.setSize(self.voxelGridResolution * self.slideCount, self.voxelGridResolution * self.slideVertCount) if self.pipeline.settings.useDebugAttachments: self.convertGridTarget.addColorTexture() self.convertGridTarget.prepareOffscreenBuffer() # Set a near-filter to the texture if self.pipeline.settings.useDebugAttachments: self.convertGridTarget.getColorTexture().setMinfilter(Texture.FTNearest) self.convertGridTarget.getColorTexture().setMagfilter(Texture.FTNearest) self.clearGridTarget = RenderTarget("ClearGIGrid") self.clearGridTarget.setSize(self.voxelGridResolution * self.slideCount, self.voxelGridResolution * self.slideVertCount) if self.pipeline.settings.useDebugAttachments: self.clearGridTarget.addColorTexture() self.clearGridTarget.prepareOffscreenBuffer() for idx, color in enumerate("rgb"): self.convertGridTarget.setShaderInput("voxelGenSrc" + color.upper(), self.generationTextures[idx]) self.clearGridTarget.setShaderInput("voxelGenTex" + color.upper(), self.generationTextures[idx]) # Create the data textures self.dataTextures = [] self.directions = ["PosX", "NegX", "PosY", "NegY", "PosZ", "NegZ"] for i, direction in enumerate(self.directions): tex = Texture("GIDataTex" + direction) tex.setup3dTexture(self.voxelGridResolution, self.voxelGridResolution, self.voxelGridResolution, Texture.TFloat, Texture.FR11G11B10) MemoryMonitor.addTexture("VoxelDataTex-" + direction, tex) self.dataTextures.append(tex) self.pipeline.getRenderPassManager().registerStaticVariable("giVoxelData" + direction, tex) # Create ping / pong textures self.pingDataTextures = [] self.pongDataTextures = [] for i, direction in enumerate(self.directions): texPing = Texture("GIPingDataTex" + direction) texPing.setup3dTexture(self.voxelGridResolution, self.voxelGridResolution, self.voxelGridResolution, Texture.TFloat, Texture.FR11G11B10) MemoryMonitor.addTexture("VoxelPingDataTex-" + direction, texPing) self.pingDataTextures.append(texPing) texPong = Texture("GIPongDataTex" + direction) texPong.setup3dTexture(self.voxelGridResolution, self.voxelGridResolution, self.voxelGridResolution, Texture.TFloat, Texture.FR11G11B10) MemoryMonitor.addTexture("VoxelPongDataTex-" + direction, texPong) self.pongDataTextures.append(texPong) self.convertGridTarget.setShaderInput("voxelDataDest"+direction, self.pingDataTextures[i]) # self.clearGridTarget.setShaderInput("voxelDataDest" + str(i), self.pongDataTextures[i]) # Set texture wrap modes for tex in self.pingDataTextures + self.pongDataTextures + self.dataTextures + self.generationTextures: tex.setMinfilter(Texture.FTLinear) tex.setMagfilter(Texture.FTLinear) tex.setWrapU(Texture.WMBorderColor) tex.setWrapV(Texture.WMBorderColor) tex.setWrapW(Texture.WMBorderColor) tex.setAnisotropicDegree(0) tex.setBorderColor(Vec4(0)) for tex in self.dataTextures: tex.setMinfilter(Texture.FTLinear) tex.setMagfilter(Texture.FTLinear) self.distributeTarget = RenderTarget("DistributeVoxels") self.distributeTarget.setSize(self.voxelGridResolution * self.slideCount, self.voxelGridResolution * self.slideVertCount) if self.pipeline.settings.useDebugAttachments: self.distributeTarget.addColorTexture() self.distributeTarget.prepareOffscreenBuffer() # Set a near-filter to the texture if self.pipeline.settings.useDebugAttachments: self.distributeTarget.getColorTexture().setMinfilter(Texture.FTNearest) self.distributeTarget.getColorTexture().setMagfilter(Texture.FTNearest) self.distributeTarget.setShaderInput("isLastStep", False) # Create solidness texture self.voxelSolidTex = Texture("GIDataSolidTex") self.voxelSolidTex.setup3dTexture(self.voxelGridResolution, self.voxelGridResolution, self.voxelGridResolution, Texture.TFloat, Texture.FR16) self.convertGridTarget.setShaderInput("voxelSolidDest", self.voxelSolidTex) self.distributeTarget.setShaderInput("voxelSolidTex", self.voxelSolidTex) MemoryMonitor.addTexture("VoxelSolidTex", self.voxelSolidTex) self.voxelSolidStableTex = Texture("GIDataSolidStableTex") self.voxelSolidStableTex.setup3dTexture(self.voxelGridResolution, self.voxelGridResolution, self.voxelGridResolution, Texture.TFloat, Texture.FR16) self.distributeTarget.setShaderInput("voxelSolidWriteTex", self.voxelSolidStableTex) self.pipeline.getRenderPassManager().registerStaticVariable("giVoxelSolidTex", self.voxelSolidStableTex) # Create the final gi pass self.finalPass = GlobalIlluminationPass() self.pipeline.getRenderPassManager().registerPass(self.finalPass) self.pipeline.getRenderPassManager().registerDynamicVariable("giData", self.bindTo) self.pipeline.getRenderPassManager().registerStaticVariable("giReadyState", self.readyStateFlag) # Visualize voxels if False: self.voxelCube = loader.loadModel("Box") self.voxelCube.reparentTo(render) # self.voxelCube.setTwoSided(True) self.voxelCube.node().setFinal(True) self.voxelCube.node().setBounds(OmniBoundingVolume()) self.voxelCube.setInstanceCount(self.voxelGridResolution**3) # self.voxelCube.hide() self.bindTo(self.voxelCube, "giData") for i in xrange(5): self.voxelCube.setShaderInput("giDataTex" + str(i), self.pingDataTextures[i]) self.disableTargets()
def setup(self): """ Setups everything for the GI to work """ # Create the voxelize pass which is used to voxelize the scene from # several directions self.voxelizePass = VoxelizePass() self.voxelizePass.setVoxelGridResolution(self.voxelGridResolution) self.voxelizePass.setVoxelGridSize(self.voxelGridSizeWS) self.voxelizePass.initVoxelStorage() self.pipeline.getRenderPassManager().registerPass(self.voxelizePass) # Create 3D Texture which is a copy of the voxel generation grid but # stable, as the generation grid is updated part by part and that would # lead to flickering self.voxelStableTex = Texture("VoxelsStable") self.voxelStableTex.setup3dTexture(self.voxelGridResolution.x, self.voxelGridResolution.y, self.voxelGridResolution.z, Texture.TFloat, Texture.FRgba8) # Set appropriate filter types: # The stable texture has mipmaps, which are generated during the process. # This is required for cone tracing. self.voxelStableTex.setMagfilter(SamplerState.FTLinear) self.voxelStableTex.setMinfilter(SamplerState.FTLinearMipmapLinear) self.voxelStableTex.setWrapU(SamplerState.WMBorderColor) self.voxelStableTex.setWrapV(SamplerState.WMBorderColor) self.voxelStableTex.setWrapW(SamplerState.WMBorderColor) self.voxelStableTex.setBorderColor(Vec4(0,0,0,0)) MemoryMonitor.addTexture("Voxel Grid Texture", self.voxelStableTex) # Setups the render target to convert the voxel grid self.convertBuffer = RenderTarget("VoxelConvertBuffer") self.convertBuffer.setSize(self.voxelGridResolution.x, self.voxelGridResolution.y) self.convertBuffer.setColorWrite(False) # self.convertBuffer.addColorTexture() self.convertBuffer.prepareOffscreenBuffer() self.convertBuffer.setShaderInput("src", self.voxelizePass.getVoxelTex()) self.convertBuffer.setShaderInput("dest", self.voxelStableTex) self.convertBuffer.setActive(False) # Store the frame index, we need that to decide which step we are currently # doing self.frameIndex = 0 # Create the various render targets to generate the mipmaps of the stable voxel grid self.mipmapTargets = [] computeSize = LVecBase3i(self.voxelGridResolution) currentMipmap = 0 while computeSize.z > 1: computeSize /= 2 target = RenderTarget("GIMiplevel" + str(currentMipmap)) target.setSize(computeSize.x, computeSize.y) target.setColorWrite(False) # target.addColorTexture() target.prepareOffscreenBuffer() target.setActive(False) target.setShaderInput("sourceMipmap", currentMipmap) target.setShaderInput("source", self.voxelStableTex) target.setShaderInput("dest", self.voxelStableTex, False, True, -1, currentMipmap + 1) self.mipmapTargets.append(target) currentMipmap += 1 # Create the final gi pass self.finalPass = GlobalIlluminationPass() self.pipeline.getRenderPassManager().registerPass(self.finalPass) self.pipeline.getRenderPassManager().registerDynamicVariable("giVoxelGridData", self.bindTo)
def initTransparencyPass(self): """ Creates the pass which renders the transparent objects into the scene """ self.transparencyPass = TransparencyPass() self.pipeline.getRenderPassManager().registerPass( self.transparencyPass) self.transparencyShadePass = TransparencyShadePass(self.pipeline) self.transparencyShadePass.setBatchSize( self.pipeline.settings.transparencyBatchSize) self.pipeline.getRenderPassManager().registerPass( self.transparencyShadePass) # Create the atomic counter which stores the amount of rendered transparent # pixels. For now this a 1x1 texture, as atomic counters are not implemented. self.pixelCountBuffer = Texture("MaterialCountBuffer") self.pixelCountBuffer.setup2dTexture(1, 1, Texture.TInt, Texture.FR32i) # Creates the buffer which stores all transparent pixels. Pixels are inserted # into the buffer in the order they are rendered, using the pixelCountBuffer # to determine their index self.materialDataBuffer = Texture("MaterialDataBuffer") self.materialDataBuffer.setupBufferTexture(self.maxPixelCount, Texture.TFloat, Texture.FRgba32, GeomEnums.UH_static) # Creates the list head buffer, which stores the first transparent pixel for # each window pixel. The index stored in this buffer is the index into the # materialDataBuffer self.listHeadBuffer = Texture("ListHeadBuffer") self.listHeadBuffer.setup2dTexture(Gloabls.resolution.x, Globals.resolution.y, Texture.TInt, Texture.FR32i) # Creates the spinlock buffer, which ensures that writing to the listHeadBuffer # is sequentially self.spinLockBuffer = Texture("SpinLockBuffer") self.spinLockBuffer.setup2dTexture(Gloabls.resolution.x, Globals.resolution.y, Texture.TInt, Texture.FR32i) # Set the buffers as input to the main scene. Maybe we can do this more elegant target = self.pipeline.showbase.render target.setShaderInput("pixelCountBuffer", self.pixelCountBuffer) target.setShaderInput("spinLockBuffer", self.spinLockBuffer) target.setShaderInput("materialDataBuffer", self.materialDataBuffer) target.setShaderInput("listHeadBuffer", self.listHeadBuffer) # Provides the buffers as global shader inputs self.pipeline.getRenderPassManager().registerStaticVariable( "transpPixelCountBuffer", self.pixelCountBuffer) self.pipeline.getRenderPassManager().registerStaticVariable( "transpSpinLockBuffer", self.spinLockBuffer) self.pipeline.getRenderPassManager().registerStaticVariable( "transpListHeadBuffer", self.listHeadBuffer) self.pipeline.getRenderPassManager().registerStaticVariable( "transpMaterialDataBuffer", self.materialDataBuffer) # Registers the transparency settings to the shaders self.pipeline.getRenderPassManager().registerDefine( "USE_TRANSPARENCY", 1) self.pipeline.getRenderPassManager().registerDefine( "MAX_TRANSPARENCY_LAYERS", self.pipeline.settings.maxTransparencyLayers) self.pipeline.getRenderPassManager().registerDefine( "TRANSPARENCY_RANGE", self.pipeline.settings.maxTransparencyRange) self.pipeline.getRenderPassManager().registerDefine( "TRANSPARENCY_BATCH_SIZE", self.pipeline.settings.transparencyBatchSize) self.pixelCountBuffer.setClearColor(Vec4(0, 0, 0, 0)) self.spinLockBuffer.setClearColor(Vec4(0, 0, 0, 0)) self.listHeadBuffer.setClearColor(Vec4(0, 0, 0, 0)) MemoryMonitor.addTexture("MaterialCountBuffer", self.pixelCountBuffer) MemoryMonitor.addTexture("MaterialDataBuffer", self.materialDataBuffer) MemoryMonitor.addTexture("ListHeadBuffer", self.listHeadBuffer) MemoryMonitor.addTexture("SpinLockBuffer", self.spinLockBuffer)