def _setBlurShader(self): """ Sets the shaders which blur the color """ blurVShader = BetterShader.load("Shader/DefaultPostProcess.vertex", "Shader/BlurVertical.fragment") blurHShader = BetterShader.load("Shader/DefaultPostProcess.vertex", "Shader/BlurHorizontal.fragment") self.blurColorV.setShader(blurVShader) self.blurColorH.setShader(blurHShader)
def _setBlurShader(self): """ Sets the shaders which blur the color """ blurVShader = BetterShader.load( "Shader/DefaultPostProcess.vertex", "Shader/BlurVertical.fragment") blurHShader = BetterShader.load( "Shader/DefaultPostProcess.vertex", "Shader/BlurHorizontal.fragment") self.blurColorV.setShader(blurVShader) self.blurColorH.setShader(blurHShader)
def _setOcclusionBlurShader(self): """ Sets the shaders which blur the occlusion """ blurVShader = BetterShader.load( "Shader/DefaultPostProcess.vertex", "Shader/BlurOcclusionVertical.fragment") blurHShader = BetterShader.load( "Shader/DefaultPostProcess.vertex", "Shader/BlurOcclusionHorizontal.fragment") self.blurOcclusionV.setShader(blurVShader) self.blurOcclusionH.setShader(blurHShader)
def reloadShader(self): edgeShader = BetterShader.load("Shader/SMAA-EdgeDetection.vertex", "Shader/SMAA-EdgeDetection.fragment") self._edgesBuffer.setShader(edgeShader) weightsShader = BetterShader.load( "Shader/SMAA-BlendingWeights.vertex", "Shader/SMAA-BlendingWeights.fragment") self._blendBuffer.setShader(weightsShader) neighborShader = BetterShader.load("Shader/SMAA-Neighbors.vertex", "Shader/SMAA-Neighbors.fragment") self._neighborBuffer.setShader(neighborShader)
def reloadShader(self): """ Reloads all used shaders """ edgeShader = BetterShader.load( "Shader/SMAA/EdgeDetection.vertex", "Shader/SMAA/EdgeDetection.fragment") self._edgesBuffer.setShader(edgeShader) weightsShader = BetterShader.load( "Shader/SMAA/BlendingWeights.vertex", "Shader/SMAA/BlendingWeights.fragment") self._blendBuffer.setShader(weightsShader) neighborShader = BetterShader.load( "Shader/SMAA/Neighbors.vertex", "Shader/SMAA/Neighbors.fragment") self._neighborBuffer.setShader(neighborShader)
def _setFinalPassShader(self): """ Sets the shader which computes the final frame, with motion blur and so on """ fShader = BetterShader.load( "Shader/DefaultPostProcess.vertex", "Shader/Final.fragment") self.deferredTarget.setShader(fShader)
def _setCombinerShader(self): """ Sets the shader which combines the lighting with the previous frame (temporal reprojection) """ cShader = BetterShader.load( "Shader/DefaultPostProcess.vertex", "Shader/Combiner.fragment") self.combiner.setShader(cShader)
def getDefaultObjectShader(self, tesselated=False): """ Returns the default shader for objects """ if not tesselated: shader = BetterShader.load( "Shader/DefaultObjectShader/vertex.glsl", "Shader/DefaultObjectShader/fragment.glsl") else: self.warn("Tesselation is only experimental! Remember " "to convert the geometry to patches first!") shader = BetterShader.load( "Shader/DefaultObjectShader/vertex.glsl", "Shader/DefaultObjectShader/fragment.glsl", "", "Shader/DefaultObjectShader/tesscontrol.glsl", "Shader/DefaultObjectShader/tesseval.glsl") return shader
def _setup(self): self.debug("Setting up render pipeline") # First, we need no transparency render.setAttrib(TransparencyAttrib.make(TransparencyAttrib.MNone), 100) # Now create deferred render buffers self._makeDeferredTargets() # Setup compute shader for lighting self._createLightingPipeline() # Setup combiner self._createCombiner() self.deferredTarget.setShader( BetterShader.load("Shader/DefaultPostProcess.vertex", "Shader/TextureDisplay.fragment")) self._setupAntialiasing() self._createFinalPass() self.antialias.getFirstBuffer().setShaderInput( "lastFrame", self.lightingComputeCombinedTex) self.antialias.getFirstBuffer().setShaderInput("lastPosition", self.lastPositionBuffer) self.antialias.getFirstBuffer().setShaderInput( "currentPosition", self.deferredTarget.getColorTexture()) # self.deferredTarget.setShaderInput("sampler", self.lightingComputeCombinedTex) # self.deferredTarget.setShaderInput("sampler", self.antialias.getResultTexture()) self.deferredTarget.setShaderInput("sampler", self.finalPass.getColorTexture()) # self.deferredTarget.setShaderInput("sampler", self.combiner.getColorTexture()) # self.deferredTarget.setShaderInput("sampler", self.lightingComputeCombinedTex) # self.deferredTarget.setShaderInput("sampler", self.antialias._neighborBuffer.getColorTexture()) # self.deferredTarget.setShaderInput("sampler", self.antialias._blendBuffer.getColorTexture()) # self.deferredTarget.setShaderInput("sampler", self.lightingComputeCombinedTex) # add update task self._attachUpdateTask() # compute first mvp self._computeMVP() self.lastLastMVP = self.lastMVP # DirectFrame(frameColor=(1, 1, 1, 0.2), frameSize=(-0.28, 0.28, -0.27, 0.4), pos=(base.getAspectRatio() - 0.35, 0.0, 0.49)) self.atlasDisplayImage = OnscreenImage( image=self.lightManager.getAtlasTex(), pos=(base.getAspectRatio() - 0.35, 0, 0.5), scale=(0.25, 0, 0.25)) self.lastPosImage = OnscreenImage( image=self.lightingComputeCombinedTex, pos=(base.getAspectRatio() - 0.35, 0, -0.05), scale=(0.25, 0, 0.25))
def getDefaultObjectShader(self, tesselated=False): """ Returns the default shader for objects """ if not tesselated: shader = BetterShader.load( "Shader/DefaultObjectShader/vertex.glsl", "Shader/DefaultObjectShader/fragment.glsl") else: self.warn( "Tesselation is only experimental! Remember " "to convert the geometry to patches first!") shader = BetterShader.load( "Shader/DefaultObjectShader/vertex.glsl", "Shader/DefaultObjectShader/fragment.glsl", "", "Shader/DefaultObjectShader/tesscontrol.glsl", "Shader/DefaultObjectShader/tesseval.glsl") return shader
def _createTagStates(self): # Create shadow caster shader self.shadowCasterShader = BetterShader.load( "Shader/DefaultShadowCaster/vertex.glsl", "Shader/DefaultShadowCaster/fragment.glsl", "Shader/DefaultShadowCaster/geometry.glsl") initialState = NodePath("ShadowCasterState") initialState.setShader(self.shadowCasterShader, 30) self.shadowComputeCamera.setTagState( "Default", initialState.getState())
def _createTagStates(self): # Create shadow caster shader self.shadowCasterShader = BetterShader.load( "Shader/DefaultShadowCaster/vertex.glsl", "Shader/DefaultShadowCaster/fragment.glsl", "Shader/DefaultShadowCaster/geometry.glsl") initialState = NodePath("ShadowCasterState") initialState.setShader(self.shadowCasterShader, 30) # initialState.setAttrib(CullFaceAttrib.make(CullFaceAttrib.MCullNone)) initialState.setAttrib(ColorWriteAttrib.make(ColorWriteAttrib.COff)) self.shadowComputeCamera.setTagState( "Default", initialState.getState())
def _createVoxelizeState(self): """ Creates the tag state and loades the voxelizer shader """ self.voxelizeShader = BetterShader.load("Shader/GI/Voxelize.vertex", "Shader/GI/Voxelize.fragment" # "Shader/GI/Voxelize.geometry" ) initialState = NodePath("VoxelizerState") initialState.setShader(self.voxelizeShader, 50) initialState.setAttrib(CullFaceAttrib.make(CullFaceAttrib.MCullNone)) initialState.setDepthWrite(False) initialState.setDepthTest(False) initialState.setAttrib(DepthTestAttrib.make(DepthTestAttrib.MNone)) initialState.setShaderInput("dv_dest_tex", self.voxelGenTex) self.voxelizeCamera.setTagState("Default", initialState.getState())
def debug3DTexture(self, tex, dest): """ Writes a 3D Texture to disk """ effectiveHeight = (tex.getYSize()+1) * (tex.getZSize()) effectiveHeight -= 1 effectiveWidth = (tex.getXSize()+1)*3 effectiveHeight = tex.getYSize() effectiveWidth = tex.getXSize() self.debug("Texture Size =",tex.getXSize(),"x",tex.getYSize(),"x",tex.getZSize()) self.debug("EffectiveHeight = ", effectiveHeight, "Layers=",tex.getZSize()) store = Texture("store") store.setup2dTexture( effectiveWidth, effectiveHeight, Texture.TFloat, Texture.FRgba16) TextureCleaner.clearTexture(store, Vec4(1,0,1,1)) # Create a dummy node and apply the shader to it shader = BetterShader.loadCompute("Shader/Write3DTexture.compute") dummy = NodePath("dummy") dummy.setShader(shader) dummy.setShaderInput("source", tex) dummy.setShaderInput("height", tex.getYSize() + 1) dummy.setShaderInput("width", tex.getXSize() + 1) dummy.setShaderInput("layerCount", tex.getZSize()) dummy.setShaderInput("destination", store) # Retrieve the underlying ShaderAttrib sattr = dummy.get_attrib(ShaderAttrib) # Dispatch the compute shader, right now! Globals.base.graphicsEngine.dispatch_compute( (tex.getXSize() / 16, tex.getYSize() / 16, tex.getZSize()), sattr, base.win.get_gsg()) Globals.base.graphicsEngine.extract_texture_data( store, Globals.base.win.getGsg()) store.write(dest)
def debug3DTexture(self, tex, dest): """ Writes a 3D Texture to disk """ effectiveHeight = (tex.getYSize() + 1) * (tex.getZSize()) effectiveHeight -= 1 effectiveWidth = (tex.getXSize() + 1) * 3 # effectiveHeight = tex.getYSize() effectiveWidth = tex.getXSize() self.debug("Texture Size =", tex.getXSize(), "x", tex.getYSize(), "x", tex.getZSize()) self.debug( "EffectiveHeight = ", effectiveHeight, "Layers=", tex.getZSize()) store = Texture("store") store.setup2dTexture( effectiveWidth, effectiveHeight, Texture.TFloat, Texture.FRgba16) TextureCleaner.clearTexture(store, Vec4(1, 0, 1, 1)) # Create a dummy node and apply the shader to it shader = BetterShader.loadCompute("Shader/Write3DTexture.compute") dummy = NodePath("dummy") dummy.setShader(shader) dummy.setShaderInput("source", tex) dummy.setShaderInput("height", tex.getYSize() + 1) dummy.setShaderInput("width", tex.getXSize() + 1) dummy.setShaderInput("layerCount", tex.getZSize()) dummy.setShaderInput("destination", store) # Retrieve the underlying ShaderAttrib sattr = dummy.get_attrib(ShaderAttrib) # Dispatch the compute shader, right now! Globals.base.graphicsEngine.dispatch_compute( (tex.getXSize() / 16, tex.getYSize() / 16, tex.getZSize()), sattr, Globals.base.win.get_gsg()) Globals.base.graphicsEngine.extract_texture_data( store, Globals.base.win.getGsg()) store.write(dest)
def _createRT(self, name, w, h, aux=False, shaderName="", layers=1): """ Internal shortcut to create a new render target """ rt = RenderTarget("Scattering" + name) rt.setSize(w, h) rt.addColorTexture() rt.setColorBits(16) # rt.setEngine(self.engine)s if aux: rt.addAuxTextures(1) rt.setAuxBits(16) if layers > 1: rt.setLayers(layers) rt.prepareOffscreenBuffer() # self._engine.openWindows() sArgs = [ "Shader/Scattering/DefaultVertex.vertex", "Shader/Scattering/" + shaderName + ".fragment" ] if layers > 1: sArgs.append("Shader/Scattering/DefaultGeometry.geometry") shader = BetterShader.load(*sArgs) rt.setShader(shader) self._setInputs(rt, "options") lc = lambda x: x[0].lower() + x[1:] for key, tex in self.textures.items(): rt.setShaderInput(lc(key), tex) self.textures[lc(name) + "Color"] = rt.getColorTexture() if aux: self.textures[lc(name) + "Aux"] = rt.getAuxTexture(0) return rt
def _createConvertShader(self): shader = BetterShader.loadCompute("Shader/GI/ConvertGrid.compute") self.convertGridNode.setShader(shader)
def _setLightingShader(self): """ Sets the shader which applies the light """ lightShader = BetterShader.load( "Shader/DefaultPostProcess.vertex", "Shader/ApplyLighting.fragment") self.lightingComputeContainer.setShader(lightShader)
def _setNormalExtractShader(self): """ Sets the shader which constructs the normals from position """ npShader = BetterShader.load("Shader/DefaultPostProcess.vertex", "Shader/ExtractNormals.fragment") self.normalPrecompute.setShader(npShader)
def _setPositionComputationShader(self): """ Sets the shader which computes the lights per tile """ pcShader = BetterShader.load("Shader/DefaultPostProcess.vertex", "Shader/PrecomputeLights.fragment") self.lightBoundsComputeBuff.setShader(pcShader)
def _setLightingShader(self): """ Sets the shader which applies the light """ lightShader = BetterShader.load("Shader/DefaultPostProcess.vertex", "Shader/ApplyLighting.fragment") self.lightingComputeContainer.setShader(lightShader)
def _setGIComputeShader(self): """ Sets the shader which computes the GI """ giShader = BetterShader.load("Shader/DefaultPostProcess.vertex", "Shader/ComputeGI.fragment") self.giPrecomputeBuffer.setShader(giShader)
def _createGenerateMipmapsShader(self): shader = BetterShader.loadCompute("Shader/GI/GenerateMipmaps.compute") self.generateMipmapsNode.setShader(shader)
def _createPopulateShader(self): shader = BetterShader.loadCompute("Shader/GI/PopulateVPL.compute") self.populateVPLNode.setShader(shader)
def reloadShader(self): """ Reloads all assigned shaders """ fxaaShader = BetterShader.load("Shader/DefaultPostProcess.vertex", "Shader/FXAA/FXAA3.fragment") self._buffer.setShader(fxaaShader)
def _createCleanShader(self): shader = BetterShader.loadCompute("Shader/GI/ClearTexture.compute") self.clearTextureNode.setShader(shader)
def _setBoxShader(self): self.box.setShader(BetterShader.load( "Shader/GI/DebugVoxels.vertex", "Shader/GI/DebugVoxels.fragment"))
def _setNormalExtractShader(self): """ Sets the shader which constructs the normals from position """ npShader = BetterShader.load( "Shader/DefaultPostProcess.vertex", "Shader/ExtractNormals.fragment") self.normalPrecompute.setShader(npShader)
def getDefaultObjectShader(self): shader = BetterShader.load("Shader/DefaultObjectShader.vertex", "Shader/DefaultObjectShader.fragment") return shader
def setup(self): """ Setups everything for the GI to work """ self.debug("Setup ..") if self.pipeline.settings.useHardwarePCF: self.error( "Global Illumination does not work in combination with PCF!") import sys sys.exit(0) return self.settings = VoxelSettingsManager() self.settings.loadFromFile(join(self.sceneRoot, "voxels.ini")) self.debug( "Loaded voxels, grid resolution is", self.settings.GridResolution) self.gridScale = self.settings.GridEnd - self.settings.GridStart self.voxelSize = self.gridScale / float(self.settings.GridResolution) self.entrySize = Vec2( 1.0 / float(self.settings.StackSizeX), 1.0 / float(self.settings.StackSizeY)) self.frameIndex = 0 invVoxelSize = Vec3( 1.0 / self.voxelSize.x, 1.0 / self.voxelSize.y, 1.0 / self.voxelSize.z) invVoxelSize.normalize() self.normalizationFactor = invVoxelSize / float(self.settings.GridResolution) # Debugging of voxels, VERY slow self.debugVoxels = False if self.debugVoxels: self.createVoxelDebugBox() # Load packed voxels packedVoxels = Globals.loader.loadTexture( join(self.sceneRoot, "voxels.png")) packedVoxels.setFormat(Texture.FRgba8) packedVoxels.setComponentType(Texture.TUnsignedByte) # packedVoxels.setKeepRamImage(False) # Create 3D Texture to store unpacked voxels self.unpackedVoxels = Texture("Unpacked voxels") self.unpackedVoxels.setup3dTexture(self.settings.GridResolution, self.settings.GridResolution, self.settings.GridResolution, Texture.TFloat, Texture.FRgba8) self.unpackedVoxels.setMinfilter(Texture.FTLinearMipmapLinear) self.unpackedVoxels.setMagfilter(Texture.FTLinear) self.unpackVoxels = NodePath("unpackVoxels") self.unpackVoxels.setShader( BetterShader.loadCompute("Shader/GI/UnpackVoxels.compute")) self.unpackVoxels.setShaderInput("packedVoxels", packedVoxels) self.unpackVoxels.setShaderInput( "stackSizeX", LVecBase3i(self.settings.StackSizeX)) self.unpackVoxels.setShaderInput("gridSize", LVecBase3i(self.settings.GridResolution)) self.unpackVoxels.setShaderInput("destination", self.unpackedVoxels) self._executeShader( self.unpackVoxels, self.settings.GridResolution / 8, self.settings.GridResolution / 8, self.settings.GridResolution / 8) # Create 3D Texture to store direct radiance self.directRadiance = Texture("Direct radiance") self.directRadiance.setup3dTexture(self.settings.GridResolution, self.settings.GridResolution, self.settings.GridResolution, Texture.TFloat, Texture.FRgba8) for prepare in [self.directRadiance, self.unpackedVoxels]: prepare.setMagfilter(Texture.FTLinear) prepare.setMinfilter(Texture.FTLinearMipmapLinear) prepare.setWrapU(Texture.WMBorderColor) prepare.setWrapV(Texture.WMBorderColor) prepare.setWrapW(Texture.WMBorderColor) prepare.setBorderColor(Vec4(0)) self.populateVPLNode = NodePath("PopulateVPLs") self.clearTextureNode = NodePath("ClearTexture") self.copyTextureNode = NodePath("CopyTexture") self.generateMipmapsNode = NodePath("GenerateMipmaps") # surroundingBox = Globals.loader.loadModel( # "Demoscene.ignore/CubeOpen/Model.egg") # surroundingBox.setPos(self.gridStart) # surroundingBox.setScale(self.gridScale) # surroundingBox.reparentTo(Globals.render) self.bindTo(self.populateVPLNode, "giData") self.reloadShader() self._generateMipmaps(self.unpackedVoxels)
def __init__(self): DebugObject.__init__(self, "LightManager") self._initArrays() # create arrays to store lights & shadow sources self.lights = [] self.shadowSources = [] self.allLightsArray = ShaderStructArray(Light, 30) self.cullBounds = None self.shadowScene = render ## SHADOW ATLAS ## # todo: move to separate class # When you change this, change also SHADOW_MAP_ATLAS_SIZE in configuration.include, # and reduce the default shadow map resolution of point lights self.shadowAtlasSize = 512 self.maxShadowMaps = 24 # When you change it , change also SHAODOW_GEOMETRY_MAX_VERTICES and # SHADOW_MAX_UPDATES_PER_FRAME in configuration.include! self.maxShadowUpdatesPerFrame = 2 self.tileSize = 128 self.tileCount = self.shadowAtlasSize / self.tileSize self.tiles = [] self.updateShadowsArray = ShaderStructArray( ShadowSource, self.maxShadowUpdatesPerFrame) self.allShadowsArray = ShaderStructArray(ShadowSource, self.maxShadowMaps) # self.shadowAtlasTex = Texture("ShadowAtlas") # self.shadowAtlasTex.setup2dTexture( # self.shadowAtlasSize, self.shadowAtlasSize, Texture.TFloat, Texture.FRg16) # self.shadowAtlasTex.setMinfilter(Texture.FTLinear) # self.shadowAtlasTex.setMagfilter(Texture.FTLinear) self.debug("Init shadow atlas with tileSize =", self.tileSize, ", tileCount =", self.tileCount) for i in xrange(self.tileCount): self.tiles.append([None for j in xrange(self.tileCount)]) # create shadow compute buffer self.shadowComputeCamera = Camera("ShadowComputeCamera") self.shadowComputeCameraNode = self.shadowScene.attachNewNode( self.shadowComputeCamera) self.shadowComputeCamera.getLens().setFov(90, 90) self.shadowComputeCamera.getLens().setNearFar(10.0, 100000.0) self.shadowComputeCameraNode.setPos(0, 0, 150) self.shadowComputeCameraNode.lookAt(0, 0, 0) self.shadowComputeTarget = RenderTarget("ShadowCompute") self.shadowComputeTarget.setSize(self.shadowAtlasSize, self.shadowAtlasSize) # self.shadowComputeTarget.setLayers(self.maxShadowUpdatesPerFrame) self.shadowComputeTarget.addRenderTexture(RenderTargetType.Depth) self.shadowComputeTarget.setDepthBits(32) self.shadowComputeTarget.setSource(self.shadowComputeCameraNode, base.win) self.shadowComputeTarget.prepareSceneRender() self.shadowComputeTarget.getInternalRegion().setSort(3) self.shadowComputeTarget.getRegion().setSort(3) self.shadowComputeTarget.getInternalRegion().setNumRegions( self.maxShadowUpdatesPerFrame + 1) self.shadowComputeTarget.getInternalRegion().setDimensions( 0, (0, 1, 0, 1)) self.shadowComputeTarget.setClearDepth(False) self.depthClearer = [] for i in xrange(self.maxShadowUpdatesPerFrame): buff = self.shadowComputeTarget.getInternalBuffer() dr = buff.makeDisplayRegion() dr.setSort(2) dr.setClearDepthActive(True) dr.setClearDepth(1.0) dr.setClearColorActive(False) dr.setDimensions(0, 0, 0, 0) self.depthClearer.append(dr) self.queuedShadowUpdates = [] # Assign copy shader self._setCopyShader() # self.shadowComputeTarget.setShaderInput("atlas", self.shadowComputeTarget.getColorTexture()) # self.shadowComputeTarget.setShaderInput( # "renderResult", self.shadowComputeTarget.getDepthTexture()) # self.shadowComputeTarget.setActive(False) # Create shadow caster shader self.shadowCasterShader = BetterShader.load( "Shader/DefaultShadowCaster.vertex", "Shader/DefaultShadowCaster.fragment", "Shader/DefaultShadowCaster.geometry") self.shadowComputeCamera.setTagStateKey("ShadowPass") initialState = NodePath("ShadowCasterState") initialState.setShader(self.shadowCasterShader, 30) self.shadowComputeCamera.setInitialState( RenderState.make(ColorWriteAttrib.make(ColorWriteAttrib.C_off), DepthWriteAttrib.make(DepthWriteAttrib.M_on), 100)) self.shadowComputeCamera.setTagState("True", initialState.getState()) self.shadowScene.setTag("ShadowPass", "True") self._createDebugTexts() self.updateShadowsArray.bindTo(self.shadowScene, "updateSources") self.updateShadowsArray.bindTo(self.shadowComputeTarget, "updateSources") self.numShadowUpdatesPTA = PTAInt.emptyArray(1) # Set initial inputs for target in [self.shadowComputeTarget, self.shadowScene]: target.setShaderInput("numUpdates", self.numShadowUpdatesPTA) self.lightingComputator = None self.lightCuller = None
def _setLightingShader(self): lightShader = BetterShader.load("Shader/DefaultPostProcess.vertex", "Shader/ApplyLighting.fragment") self.lightingComputeContainer.setShader(lightShader)
def _setCombinerShader(self): cShader = BetterShader.load("Shader/DefaultPostProcess.vertex", "Shader/Combiner.fragment") self.combiner.setShader(cShader)
def _setCombinerShader(self): """ Sets the shader which combines the lighting with the previous frame (temporal reprojection) """ cShader = BetterShader.load("Shader/DefaultPostProcess.vertex", "Shader/Combiner.fragment") self.combiner.setShader(cShader)
def _setPositionComputationShader(self): pcShader = BetterShader.load("Shader/DefaultPostProcess.vertex", "Shader/PrecomputeLights.fragment") self.lightBoundsComputeBuff.setShader(pcShader)
def _setFinalPassShader(self): """ Sets the shader which computes the final frame, with motion blur and so on """ fShader = BetterShader.load("Shader/DefaultPostProcess.vertex", "Shader/Final.fragment") self.deferredTarget.setShader(fShader)
def _setFinalPassShader(self): fShader = BetterShader.load("Shader/DefaultPostProcess.vertex", "Shader/Final.fragment") self.finalPass.setShader(fShader)
def _createCopyShader(self): shader = BetterShader.loadCompute("Shader/GI/CopyResult.compute") self.copyTextureNode.setShader(shader)
def _setPositionComputationShader(self): """ Sets the shader which computes the lights per tile """ pcShader = BetterShader.load( "Shader/DefaultPostProcess.vertex", "Shader/PrecomputeLights.fragment") self.lightBoundsComputeBuff.setShader(pcShader)