def __init__(self, app): gobject.GObject.__init__(self) self.app = app self.blocks = {} self.wcf_uid_list = [] self.chrono_times = {} self.chrono_day = time.localtime().tm_wday if not os.path.exists(BLOCK_DB): try: os.makedirs(os.path.dirname(BLOCK_DB)) except: pass else: try: db = open(BLOCK_DB, 'rb') p = pickle.load(db) self.blocks = p[0] self.wcf_uid_list = p[1] self.chrono_times = p[2] self.chrono_day = p[3] db.close() except: print "Something wrong unpickling" self.__next_update_info = None self.usersmanager = UsersManager() if os.name == "nt": self.win32top = Win32Top(self) self.chrono = Chrono(self) self.firewall_filter = FirewallFilter(self) self.filter_manager = FilterManager(self) self.webcontent_filter = WebContentFilter(self, app) self.session_filter = SessionFilter(self) gobject.timeout_add(1000, self.__polling_cb)
def __init__(self, win, cam): self.manager = FilterManager(win, cam) self.configuration = {} self.task = None self.cleanup()
class CommonFilters: def __init__(self, win, cam): self.manager = FilterManager(win, cam) self.configuration = {} self.task = None self.cleanup() def loadShader(self, name): fn = os.path.join(os.path.abspath(os.path.dirname(__file__)), name) fn = Filename.fromOsSpecific(fn) fn.makeTrueCase() return Shader.load(fn) def cleanup(self): self.manager.cleanup() self.textures = {} self.finalQuad = None self.bloom = [] self.blur = [] self.ssao = [] if self.task != None: taskMgr.remove(self.task) self.task = None def reconfigure(self, fullrebuild, changed): configuration = self.configuration if fullrebuild: self.cleanup() if len(configuration) == 0: return None auxbits = 0 needtex = {} needtex['color'] = True if configuration.has_key('CartoonInk'): needtex['aux'] = True auxbits |= AuxBitplaneAttrib.ABOAuxNormal if configuration.has_key('AmbientOcclusion'): needtex['depth'] = True needtex['ssao0'] = True needtex['ssao1'] = True needtex['ssao2'] = True needtex['aux'] = True auxbits |= AuxBitplaneAttrib.ABOAuxNormal if configuration.has_key('BlurSharpen'): needtex['blur0'] = True needtex['blur1'] = True if configuration.has_key('Bloom'): needtex['bloom0'] = True needtex['bloom1'] = True needtex['bloom2'] = True needtex['bloom3'] = True auxbits |= AuxBitplaneAttrib.ABOGlow if configuration.has_key('ViewGlow'): auxbits |= AuxBitplaneAttrib.ABOGlow for tex in needtex: self.textures[tex] = Texture('scene-' + tex) self.textures[tex].setWrapU(Texture.WMClamp) self.textures[tex].setWrapV(Texture.WMClamp) needtexpix = True self.finalQuad = self.manager.renderSceneInto( textures=self.textures, auxbits=auxbits) if self.finalQuad == None: self.cleanup() return False if configuration.has_key('BlurSharpen'): blur0 = self.textures['blur0'] blur1 = self.textures['blur1'] self.blur.append( self.manager.renderQuadInto(colortex=blur0, div=2)) self.blur.append(self.manager.renderQuadInto(colortex=blur1)) self.blur[0].setShaderInput('src', self.textures['color']) self.blur[0].setShader(self.loadShader('filter-blurx.sha')) self.blur[1].setShaderInput('src', blur0) self.blur[1].setShader(self.loadShader('filter-blury.sha')) if configuration.has_key('AmbientOcclusion'): ssao0 = self.textures['ssao0'] ssao1 = self.textures['ssao1'] ssao2 = self.textures['ssao2'] self.ssao.append(self.manager.renderQuadInto(colortex=ssao0)) self.ssao.append( self.manager.renderQuadInto(colortex=ssao1, div=2)) self.ssao.append(self.manager.renderQuadInto(colortex=ssao2)) self.ssao[0].setShaderInput('depth', self.textures['depth']) self.ssao[0].setShaderInput('normal', self.textures['aux']) self.ssao[0].setShaderInput( 'random', loader.loadTexture('maps/random.rgb')) self.ssao[0].setShader(self.loadShader('filter-ssao.sha')) self.ssao[1].setShaderInput('src', ssao0) self.ssao[1].setShader(self.loadShader('filter-blurx.sha')) self.ssao[2].setShaderInput('src', ssao1) self.ssao[2].setShader(self.loadShader('filter-blury.sha')) if configuration.has_key('Bloom'): bloomconf = configuration['Bloom'] bloom0 = self.textures['bloom0'] bloom1 = self.textures['bloom1'] bloom2 = self.textures['bloom2'] bloom3 = self.textures['bloom3'] if bloomconf.size == 'large': scale = 8 downsampler = 'filter-down4.sha' elif bloomconf.size == 'medium': scale = 4 downsampler = 'filter-copy.sha' else: scale = 2 downsampler = 'filter-copy.sha' self.bloom.append( self.manager.renderQuadInto(colortex=bloom0, div=2, align=scale)) self.bloom.append( self.manager.renderQuadInto(colortex=bloom1, div=scale, align=scale)) self.bloom.append( self.manager.renderQuadInto(colortex=bloom2, div=scale, align=scale)) self.bloom.append( self.manager.renderQuadInto(colortex=bloom3, div=scale, align=scale)) self.bloom[0].setShaderInput('src', self.textures['color']) self.bloom[0].setShader(self.loadShader('filter-bloomi.sha')) self.bloom[1].setShaderInput('src', bloom0) self.bloom[1].setShader(self.loadShader(downsampler)) self.bloom[2].setShaderInput('src', bloom1) self.bloom[2].setShader(self.loadShader('filter-bloomx.sha')) self.bloom[3].setShaderInput('src', bloom2) self.bloom[3].setShader(self.loadShader('filter-bloomy.sha')) text = '//Cg\n' text += 'void vshader(float4 vtx_position : POSITION,\n' text += ' out float4 l_position : POSITION,\n' text += ' uniform float4 texpad_txcolor,\n' text += ' uniform float4 texpix_txcolor,\n' text += ' out float4 l_texcoordC : TEXCOORD0,\n' if configuration.has_key('CartoonInk'): text += ' uniform float4 texpad_txaux,\n' text += ' uniform float4 texpix_txaux,\n' text += ' out float4 l_texcoordN : TEXCOORD1,\n' if configuration.has_key('Bloom'): text += ' uniform float4 texpad_txbloom3,\n' text += ' out float4 l_texcoordB : TEXCOORD2,\n' if configuration.has_key('BlurSharpen'): text += ' uniform float4 texpad_txblur1,\n' text += ' out float4 l_texcoordBS : TEXCOORD3,\n' if configuration.has_key('AmbientOcclusion'): text += ' uniform float4 texpad_txssao2,\n' text += ' out float4 l_texcoordAO : TEXCOORD4,\n' text += ' uniform float4x4 mat_modelproj)\n' text += '{\n' text += ' l_position=mul(mat_modelproj, vtx_position);\n' text += ' l_texcoordC=(vtx_position.xzxz * texpad_txcolor) + texpad_txcolor;\n' if configuration.has_key('CartoonInk'): text += ' l_texcoordN=(vtx_position.xzxz * texpad_txaux) + texpad_txaux;\n' if configuration.has_key('Bloom'): text += ' l_texcoordB=(vtx_position.xzxz * texpad_txbloom3) + texpad_txbloom3;\n' if configuration.has_key('BlurSharpen'): text += ' l_texcoordBS=(vtx_position.xzxz * texpad_txblur1) + texpad_txblur1;\n' if configuration.has_key('AmbientOcclusion'): text += ' l_texcoordAO=(vtx_position.xzxz * texpad_txssao2) + texpad_txssao2;\n' if configuration.has_key('HalfPixelShift'): text += ' l_texcoordC+=texpix_txcolor*0.5;\n' if configuration.has_key('CartoonInk'): text += ' l_texcoordN+=texpix_txaux*0.5;\n' text += '}\n' text += 'void fshader(\n' text += 'float4 l_texcoordC : TEXCOORD0,\n' text += 'uniform float4 texpix_txcolor,\n' if configuration.has_key('CartoonInk'): text += 'float4 l_texcoordN : TEXCOORD1,\n' text += 'uniform float4 texpix_txaux,\n' if configuration.has_key('Bloom'): text += 'float4 l_texcoordB : TEXCOORD2,\n' if configuration.has_key('BlurSharpen'): text += 'float4 l_texcoordBS : TEXCOORD3,\n' text += 'uniform float4 k_blurval,\n' if configuration.has_key('AmbientOcclusion'): text += 'float4 l_texcoordAO : TEXCOORD4,\n' for key in self.textures: text += 'uniform sampler2D k_tx' + key + ',\n' if configuration.has_key('CartoonInk'): text += 'uniform float4 k_cartoonseparation,\n' if configuration.has_key('VolumetricLighting'): text += 'uniform float4 k_casterpos,\n' text += 'uniform float4 k_vlparams,\n' text += 'out float4 o_color : COLOR)\n' text += '{\n' text += ' o_color = tex2D(k_txcolor, l_texcoordC.xy);\n' if configuration.has_key('CartoonInk'): text += CARTOON_BODY if configuration.has_key('AmbientOcclusion'): text += 'o_color *= tex2D(k_txssao2, l_texcoordAO.xy).r;\n' if configuration.has_key('BlurSharpen'): text += ' o_color = lerp(tex2D(k_txblur1, l_texcoordBS.xy), o_color, k_blurval.x);\n' if configuration.has_key('Bloom'): text += 'o_color = saturate(o_color);\n' text += 'float4 bloom = 0.5*tex2D(k_txbloom3, l_texcoordB.xy);\n' text += 'o_color = 1-((1-bloom)*(1-o_color));\n' if configuration.has_key('ViewGlow'): text += 'o_color.r = o_color.a;\n' if configuration.has_key('VolumetricLighting'): text += 'float decay = 1.0f;\n' text += 'float2 curcoord = l_texcoordC.xy;\n' text += 'float2 lightdir = curcoord - k_casterpos.xy;\n' text += 'lightdir *= k_vlparams.y;\n' text += 'half4 sample = tex2D(k_txcolor, curcoord);\n' text += 'float3 vlcolor = sample.rgb * sample.a;\n' text += 'for (int i = 0; i < k_vlparams.x; i++) {\n' text += ' curcoord -= lightdir;\n' text += ' sample = tex2D(k_txcolor, curcoord);\n' text += ' sample *= sample.a * decay;//*weight\n' text += ' vlcolor += sample.rgb;\n' text += ' decay *= k_vlparams.z;\n' text += '}\n' text += 'o_color += float4(vlcolor * k_vlparams.w, 1);\n' if configuration.has_key('Inverted'): text += 'o_color = float4(1, 1, 1, 1) - o_color;\n' text += '}\n' self.finalQuad.setShader(Shader.make(text)) for tex in self.textures: self.finalQuad.setShaderInput('tx' + tex, self.textures[tex]) self.task = taskMgr.add(self.update, 'common-filters-update') if changed == 'CartoonInk' or fullrebuild: if configuration.has_key('CartoonInk'): separation = configuration['CartoonInk'] self.finalQuad.setShaderInput( 'cartoonseparation', Vec4(separation, 0, separation, 0)) if changed == 'BlurSharpen' or fullrebuild: if configuration.has_key('BlurSharpen'): blurval = configuration['BlurSharpen'] self.finalQuad.setShaderInput( 'blurval', Vec4(blurval, blurval, blurval, blurval)) if changed == 'Bloom' or fullrebuild: if configuration.has_key('Bloom'): bloomconf = configuration['Bloom'] intensity = bloomconf.intensity * 3.0 self.bloom[0].setShaderInput('blend', bloomconf.blendx, bloomconf.blendy, bloomconf.blendz, bloomconf.blendw * 2.0) self.bloom[0].setShaderInput( 'trigger', bloomconf.mintrigger, 1.0 / (bloomconf.maxtrigger - bloomconf.mintrigger), 0.0, 0.0) self.bloom[0].setShaderInput('desat', bloomconf.desat) self.bloom[3].setShaderInput('intensity', intensity, intensity, intensity, intensity) if changed == 'VolumetricLighting' or fullrebuild: if configuration.has_key('VolumetricLighting'): config = configuration['VolumetricLighting'] tcparam = config.density / float(config.numsamples) self.finalQuad.setShaderInput('vlparams', config.numsamples, tcparam, config.decay, config.exposure) if changed == 'AmbientOcclusion' or fullrebuild: if configuration.has_key('AmbientOcclusion'): config = configuration['AmbientOcclusion'] self.ssao[0].setShaderInput( 'params1', config.numsamples, -float(config.amount) / config.numsamples, config.radius, 0) self.ssao[0].setShaderInput('params2', config.strength, config.falloff, 0, 0) self.update() return True def update(self, task=None): if self.configuration.has_key('VolumetricLighting'): caster = self.configuration['VolumetricLighting'].caster casterpos = Point2() self.manager.camera.node().getLens().project( caster.getPos(self.manager.camera), casterpos) self.finalQuad.setShaderInput( 'casterpos', Vec4(casterpos.getX() * 0.5 + 0.5, casterpos.getY() * 0.5 + 0.5, 0, 0)) if task != None: return task.cont def setCartoonInk(self, separation=1): fullrebuild = self.configuration.has_key('CartoonInk') == False self.configuration['CartoonInk'] = separation return self.reconfigure(fullrebuild, 'CartoonInk') def delCartoonInk(self): if self.configuration.has_key('CartoonInk'): del self.configuration['CartoonInk'] return self.reconfigure(True, 'CartoonInk') return True def setBloom(self, blend=(0.29999999999999999, 0.40000000000000002, 0.29999999999999999, 0.0), mintrigger=0.59999999999999998, maxtrigger=1.0, desat=0.59999999999999998, intensity=1.0, size='medium'): if size == 0: size = 'off' elif size == 1: size = 'small' elif size == 2: size = 'medium' elif size == 3: size = 'large' if size == 'off': self.delBloom() return None if maxtrigger == None: maxtrigger = mintrigger + 0.80000000000000004 oldconfig = self.configuration.get('Bloom', None) fullrebuild = True if oldconfig and oldconfig.size == size: fullrebuild = False newconfig = FilterConfig() (newconfig.blendx, newconfig.blendy, newconfig.blendz, newconfig.blendw) = blend newconfig.maxtrigger = maxtrigger newconfig.mintrigger = mintrigger newconfig.desat = desat newconfig.intensity = intensity newconfig.size = size self.configuration['Bloom'] = newconfig return self.reconfigure(fullrebuild, 'Bloom') def delBloom(self): if self.configuration.has_key('Bloom'): del self.configuration['Bloom'] return self.reconfigure(True, 'Bloom') return True def setHalfPixelShift(self): fullrebuild = self.configuration.has_key('HalfPixelShift') == False self.configuration['HalfPixelShift'] = 1 return self.reconfigure(fullrebuild, 'HalfPixelShift') def delHalfPixelShift(self): if self.configuration.has_key('HalfPixelShift'): del self.configuration['HalfPixelShift'] return self.reconfigure(True, 'HalfPixelShift') return True def setViewGlow(self): fullrebuild = self.configuration.has_key('ViewGlow') == False self.configuration['ViewGlow'] = 1 return self.reconfigure(fullrebuild, 'ViewGlow') def delViewGlow(self): if self.configuration.has_key('ViewGlow'): del self.configuration['ViewGlow'] return self.reconfigure(True, 'ViewGlow') return True def setInverted(self): fullrebuild = self.configuration.has_key('Inverted') == False self.configuration['Inverted'] = 1 return self.reconfigure(fullrebuild, 'Inverted') def delInverted(self): if self.configuration.has_key('Inverted'): del self.configuration['Inverted'] return self.reconfigure(True, 'Inverted') return True def setVolumetricLighting(self, caster, numsamples=32, density=5.0, decay=0.10000000000000001, exposure=0.10000000000000001): fullrebuild = self.configuration.has_key('VolumetricLighting') == False newconfig = FilterConfig() newconfig.caster = caster newconfig.numsamples = numsamples newconfig.density = density newconfig.decay = decay newconfig.exposure = exposure self.configuration['VolumetricLighting'] = newconfig return self.reconfigure(fullrebuild, 'VolumetricLighting') def delVolumetricLighting(self): if self.configuration.has_key('VolumetricLighting'): del self.configuration['VolumetricLighting'] return self.reconfigure(True, 'VolumetricLighting') return True def setBlurSharpen(self, amount=0.0): fullrebuild = self.configuration.has_key('BlurSharpen') == False self.configuration['BlurSharpen'] = amount return self.reconfigure(fullrebuild, 'BlurSharpen') def delBlurSharpen(self): if self.configuration.has_key('BlurSharpen'): del self.configuration['BlurSharpen'] return self.reconfigure(True, 'BlurSharpen') return True def setAmbientOcclusion(self, numsamples=16, radius=0.050000000000000003, amount=2.0, strength=0.01, falloff=1.9999999999999999e-006): fullrebuild = self.configuration.has_key('AmbientOcclusion') == False newconfig = FilterConfig() newconfig.numsamples = numsamples newconfig.radius = radius newconfig.amount = amount newconfig.strength = strength newconfig.falloff = falloff self.configuration['AmbientOcclusion'] = newconfig return self.reconfigure(fullrebuild, 'AmbientOcclusion') def delAmbientOcclusion(self): if self.configuration.has_key('AmbientOcclusion'): del self.configuration['AmbientOcclusion'] return self.reconfigure(True, 'AmbientOcclusion') return True
def __init__(self, win, cam): self.manager = FilterManager(win, cam) self.configuration = {} self.task = None self.cleanup()
class CommonFilters: """ Class CommonFilters implements certain common image postprocessing filters. The constructor requires a filter builder as a parameter. """ def __init__(self, win, cam): self.manager = FilterManager(win, cam) self.configuration = {} self.task = None self.cleanup() def loadShader(self, name): fn = os.path.join(os.path.abspath(os.path.dirname(__file__)), name) fn = Filename.fromOsSpecific(fn) fn.makeTrueCase() return Shader.load(fn) def cleanup(self): self.manager.cleanup() self.textures = {} self.finalQuad = None self.bloom = [] self.blur = [] self.ssao = [] if self.task != None: taskMgr.remove(self.task) self.task = None def reconfigure(self, fullrebuild, changed): """ Reconfigure is called whenever any configuration change is made. """ configuration = self.configuration if fullrebuild: self.cleanup() if len(configuration) == 0: return auxbits = 0 needtex = {} needtex["color"] = True if configuration.has_key("CartoonInk"): needtex["aux"] = True auxbits |= AuxBitplaneAttrib.ABOAuxNormal if configuration.has_key("AmbientOcclusion"): needtex["depth"] = True needtex["ssao0"] = True needtex["ssao1"] = True needtex["ssao2"] = True needtex["aux"] = True auxbits |= AuxBitplaneAttrib.ABOAuxNormal if configuration.has_key("BlurSharpen"): needtex["blur0"] = True needtex["blur1"] = True if configuration.has_key("Bloom"): needtex["bloom0"] = True needtex["bloom1"] = True needtex["bloom2"] = True needtex["bloom3"] = True auxbits |= AuxBitplaneAttrib.ABOGlow if configuration.has_key("ViewGlow"): auxbits |= AuxBitplaneAttrib.ABOGlow for tex in needtex: self.textures[tex] = Texture("scene-" + tex) self.textures[tex].setWrapU(Texture.WMClamp) self.textures[tex].setWrapV(Texture.WMClamp) needtexpix = True self.finalQuad = self.manager.renderSceneInto(textures=self.textures, auxbits=auxbits) if self.finalQuad == None: self.cleanup() return False if configuration.has_key("BlurSharpen"): blur0 = self.textures["blur0"] blur1 = self.textures["blur1"] self.blur.append(self.manager.renderQuadInto(colortex=blur0, div=2)) self.blur.append(self.manager.renderQuadInto(colortex=blur1)) self.blur[0].setShaderInput("src", self.textures["color"]) self.blur[0].setShader(self.loadShader("filter-blurx.sha")) self.blur[1].setShaderInput("src", blur0) self.blur[1].setShader(self.loadShader("filter-blury.sha")) if configuration.has_key("AmbientOcclusion"): ssao0 = self.textures["ssao0"] ssao1 = self.textures["ssao1"] ssao2 = self.textures["ssao2"] self.ssao.append(self.manager.renderQuadInto(colortex=ssao0)) self.ssao.append(self.manager.renderQuadInto(colortex=ssao1, div=2)) self.ssao.append(self.manager.renderQuadInto(colortex=ssao2)) self.ssao[0].setShaderInput("depth", self.textures["depth"]) self.ssao[0].setShaderInput("normal", self.textures["aux"]) self.ssao[0].setShaderInput("random", loader.loadTexture("maps/random.rgb")) self.ssao[0].setShader(self.loadShader("filter-ssao.sha")) self.ssao[1].setShaderInput("src", ssao0) self.ssao[1].setShader(self.loadShader("filter-blurx.sha")) self.ssao[2].setShaderInput("src", ssao1) self.ssao[2].setShader(self.loadShader("filter-blury.sha")) if configuration.has_key("Bloom"): bloomconf = configuration["Bloom"] bloom0 = self.textures["bloom0"] bloom1 = self.textures["bloom1"] bloom2 = self.textures["bloom2"] bloom3 = self.textures["bloom3"] if bloomconf.size == "large": scale = 8 downsampler = "filter-down4.sha" elif bloomconf.size == "medium": scale = 4 downsampler = "filter-copy.sha" else: scale = 2 downsampler = "filter-copy.sha" self.bloom.append(self.manager.renderQuadInto(colortex=bloom0, div=2, align=scale)) self.bloom.append(self.manager.renderQuadInto(colortex=bloom1, div=scale, align=scale)) self.bloom.append(self.manager.renderQuadInto(colortex=bloom2, div=scale, align=scale)) self.bloom.append(self.manager.renderQuadInto(colortex=bloom3, div=scale, align=scale)) self.bloom[0].setShaderInput("src", self.textures["color"]) self.bloom[0].setShader(self.loadShader("filter-bloomi.sha")) self.bloom[1].setShaderInput("src", bloom0) self.bloom[1].setShader(self.loadShader(downsampler)) self.bloom[2].setShaderInput("src", bloom1) self.bloom[2].setShader(self.loadShader("filter-bloomx.sha")) self.bloom[3].setShaderInput("src", bloom2) self.bloom[3].setShader(self.loadShader("filter-bloomy.sha")) text = "//Cg\n" text += "void vshader(float4 vtx_position : POSITION,\n" text += " out float4 l_position : POSITION,\n" text += " uniform float4 texpad_txcolor,\n" text += " uniform float4 texpix_txcolor,\n" text += " out float4 l_texcoordC : TEXCOORD0,\n" if configuration.has_key("CartoonInk"): text += " uniform float4 texpad_txaux,\n" text += " uniform float4 texpix_txaux,\n" text += " out float4 l_texcoordN : TEXCOORD1,\n" if configuration.has_key("Bloom"): text += " uniform float4 texpad_txbloom3,\n" text += " out float4 l_texcoordB : TEXCOORD2,\n" if configuration.has_key("BlurSharpen"): text += " uniform float4 texpad_txblur1,\n" text += " out float4 l_texcoordBS : TEXCOORD3,\n" if configuration.has_key("AmbientOcclusion"): text += " uniform float4 texpad_txssao2,\n" text += " out float4 l_texcoordAO : TEXCOORD4,\n" text += " uniform float4x4 mat_modelproj)\n" text += "{\n" text += " l_position=mul(mat_modelproj, vtx_position);\n" text += " l_texcoordC=(vtx_position.xzxz * texpad_txcolor) + texpad_txcolor;\n" if configuration.has_key("CartoonInk"): text += " l_texcoordN=(vtx_position.xzxz * texpad_txaux) + texpad_txaux;\n" if configuration.has_key("Bloom"): text += " l_texcoordB=(vtx_position.xzxz * texpad_txbloom3) + texpad_txbloom3;\n" if configuration.has_key("BlurSharpen"): text += " l_texcoordBS=(vtx_position.xzxz * texpad_txblur1) + texpad_txblur1;\n" if configuration.has_key("AmbientOcclusion"): text += " l_texcoordAO=(vtx_position.xzxz * texpad_txssao2) + texpad_txssao2;\n" if configuration.has_key("HalfPixelShift"): text += " l_texcoordC+=texpix_txcolor*0.5;\n" if configuration.has_key("CartoonInk"): text += " l_texcoordN+=texpix_txaux*0.5;\n" text += "}\n" text += "void fshader(\n" text += "float4 l_texcoordC : TEXCOORD0,\n" text += "uniform float4 texpix_txcolor,\n" if configuration.has_key("CartoonInk"): text += "float4 l_texcoordN : TEXCOORD1,\n" text += "uniform float4 texpix_txaux,\n" if configuration.has_key("Bloom"): text += "float4 l_texcoordB : TEXCOORD2,\n" if configuration.has_key("BlurSharpen"): text += "float4 l_texcoordBS : TEXCOORD3,\n" text += "uniform float4 k_blurval,\n" if configuration.has_key("AmbientOcclusion"): text += "float4 l_texcoordAO : TEXCOORD4,\n" for key in self.textures: text += "uniform sampler2D k_tx" + key + ",\n" if configuration.has_key("CartoonInk"): text += "uniform float4 k_cartoonseparation,\n" if configuration.has_key("VolumetricLighting"): text += "uniform float4 k_casterpos,\n" text += "uniform float4 k_vlparams,\n" text += "out float4 o_color : COLOR)\n" text += "{\n" text += " o_color = tex2D(k_txcolor, l_texcoordC.xy);\n" if configuration.has_key("CartoonInk"): text += CARTOON_BODY if configuration.has_key("AmbientOcclusion"): text += "o_color *= tex2D(k_txssao2, l_texcoordAO.xy).r;\n" if configuration.has_key("BlurSharpen"): text += " o_color = lerp(tex2D(k_txblur1, l_texcoordBS.xy), o_color, k_blurval.x);\n" if configuration.has_key("Bloom"): text += "o_color = saturate(o_color);\n" text += "float4 bloom = 0.5*tex2D(k_txbloom3, l_texcoordB.xy);\n" text += "o_color = 1-((1-bloom)*(1-o_color));\n" if configuration.has_key("ViewGlow"): text += "o_color.r = o_color.a;\n" if configuration.has_key("VolumetricLighting"): text += "float decay = 1.0f;\n" text += "float2 curcoord = l_texcoordC.xy;\n" text += "float2 lightdir = curcoord - k_casterpos.xy;\n" text += "lightdir *= k_vlparams.x;\n" text += "half4 sample = tex2D(k_txcolor, curcoord);\n" text += "float3 vlcolor = sample.rgb * sample.a;\n" text += "for (int i = 0; i < %s; i++) {\n" % int(configuration["VolumetricLighting"].numsamples) text += " curcoord -= lightdir;\n" text += " sample = tex2D(k_txcolor, curcoord);\n" text += " sample *= sample.a * decay;//*weight\n" text += " vlcolor += sample.rgb;\n" text += " decay *= k_vlparams.y;\n" text += "}\n" text += "o_color += float4(vlcolor * k_vlparams.z, 1);\n" if configuration.has_key("Inverted"): text += "o_color = float4(1, 1, 1, 1) - o_color;\n" text += "}\n" self.finalQuad.setShader(Shader.make(text)) for tex in self.textures: self.finalQuad.setShaderInput("tx" + tex, self.textures[tex]) self.task = taskMgr.add(self.update, "common-filters-update") if (changed == "CartoonInk") or fullrebuild: if configuration.has_key("CartoonInk"): separation = configuration["CartoonInk"] self.finalQuad.setShaderInput("cartoonseparation", Vec4(separation, 0, separation, 0)) if (changed == "BlurSharpen") or fullrebuild: if configuration.has_key("BlurSharpen"): blurval = configuration["BlurSharpen"] self.finalQuad.setShaderInput("blurval", Vec4(blurval, blurval, blurval, blurval)) if (changed == "Bloom") or fullrebuild: if configuration.has_key("Bloom"): bloomconf = configuration["Bloom"] intensity = bloomconf.intensity * 3.0 self.bloom[0].setShaderInput( "blend", bloomconf.blendx, bloomconf.blendy, bloomconf.blendz, bloomconf.blendw * 2.0 ) self.bloom[0].setShaderInput( "trigger", bloomconf.mintrigger, 1.0 / (bloomconf.maxtrigger - bloomconf.mintrigger), 0.0, 0.0 ) self.bloom[0].setShaderInput("desat", bloomconf.desat) self.bloom[3].setShaderInput("intensity", intensity, intensity, intensity, intensity) if (changed == "VolumetricLighting") or fullrebuild: if configuration.has_key("VolumetricLighting"): config = configuration["VolumetricLighting"] tcparam = config.density / float(config.numsamples) self.finalQuad.setShaderInput("vlparams", tcparam, config.decay, config.exposure, 0.0) if (changed == "AmbientOcclusion") or fullrebuild: if configuration.has_key("AmbientOcclusion"): config = configuration["AmbientOcclusion"] self.ssao[0].setShaderInput( "params1", config.numsamples, -float(config.amount) / config.numsamples, config.radius, 0 ) self.ssao[0].setShaderInput("params2", config.strength, config.falloff, 0, 0) self.update() return True def update(self, task=None): """Updates the shader inputs that need to be updated every frame. Normally, you shouldn't call this, it's being called in a task.""" if self.configuration.has_key("VolumetricLighting"): caster = self.configuration["VolumetricLighting"].caster casterpos = Point2() self.manager.camera.node().getLens().project(caster.getPos(self.manager.camera), casterpos) self.finalQuad.setShaderInput( "casterpos", Vec4(casterpos.getX() * 0.5 + 0.5, (casterpos.getY() * 0.5 + 0.5), 0, 0) ) if task != None: return task.cont def setCartoonInk(self, separation=1): fullrebuild = self.configuration.has_key("CartoonInk") == False self.configuration["CartoonInk"] = separation return self.reconfigure(fullrebuild, "CartoonInk") def delCartoonInk(self): if self.configuration.has_key("CartoonInk"): del self.configuration["CartoonInk"] return self.reconfigure(True, "CartoonInk") return True def setBloom( self, blend=(0.3, 0.4, 0.3, 0.0), mintrigger=0.6, maxtrigger=1.0, desat=0.6, intensity=1.0, size="medium" ): if size == 0: size = "off" elif size == 1: size = "small" elif size == 2: size = "medium" elif size == 3: size = "large" if size == "off": self.delBloom() return if maxtrigger == None: maxtrigger = mintrigger + 0.8 oldconfig = self.configuration.get("Bloom", None) fullrebuild = True if (oldconfig) and (oldconfig.size == size): fullrebuild = False newconfig = FilterConfig() (newconfig.blendx, newconfig.blendy, newconfig.blendz, newconfig.blendw) = blend newconfig.maxtrigger = maxtrigger newconfig.mintrigger = mintrigger newconfig.desat = desat newconfig.intensity = intensity newconfig.size = size self.configuration["Bloom"] = newconfig return self.reconfigure(fullrebuild, "Bloom") def delBloom(self): if self.configuration.has_key("Bloom"): del self.configuration["Bloom"] return self.reconfigure(True, "Bloom") return True def setHalfPixelShift(self): fullrebuild = self.configuration.has_key("HalfPixelShift") == False self.configuration["HalfPixelShift"] = 1 return self.reconfigure(fullrebuild, "HalfPixelShift") def delHalfPixelShift(self): if self.configuration.has_key("HalfPixelShift"): del self.configuration["HalfPixelShift"] return self.reconfigure(True, "HalfPixelShift") return True def setViewGlow(self): fullrebuild = self.configuration.has_key("ViewGlow") == False self.configuration["ViewGlow"] = 1 return self.reconfigure(fullrebuild, "ViewGlow") def delViewGlow(self): if self.configuration.has_key("ViewGlow"): del self.configuration["ViewGlow"] return self.reconfigure(True, "ViewGlow") return True def setInverted(self): fullrebuild = self.configuration.has_key("Inverted") == False self.configuration["Inverted"] = 1 return self.reconfigure(fullrebuild, "Inverted") def delInverted(self): if self.configuration.has_key("Inverted"): del self.configuration["Inverted"] return self.reconfigure(True, "Inverted") return True def setVolumetricLighting(self, caster, numsamples=32, density=5.0, decay=0.1, exposure=0.1): oldconfig = self.configuration.get("VolumetricLighting", None) fullrebuild = True if (oldconfig) and (oldconfig.caster == caster): fullrebuild = False newconfig = FilterConfig() newconfig.caster = caster newconfig.numsamples = int(numsamples) newconfig.density = density newconfig.decay = decay newconfig.exposure = exposure self.configuration["VolumetricLighting"] = newconfig return self.reconfigure(fullrebuild, "VolumetricLighting") def delVolumetricLighting(self): if self.configuration.has_key("VolumetricLighting"): del self.configuration["VolumetricLighting"] return self.reconfigure(True, "VolumetricLighting") return True def setBlurSharpen(self, amount=0.0): """Enables the blur/sharpen filter. If the 'amount' parameter is 1.0, it will not have effect. A value of 0.0 means fully blurred, and a value higher than 1.0 sharpens the image.""" fullrebuild = self.configuration.has_key("BlurSharpen") == False self.configuration["BlurSharpen"] = amount return self.reconfigure(fullrebuild, "BlurSharpen") def delBlurSharpen(self): if self.configuration.has_key("BlurSharpen"): del self.configuration["BlurSharpen"] return self.reconfigure(True, "BlurSharpen") return True def setAmbientOcclusion(self, numsamples=16, radius=0.05, amount=2.0, strength=0.01, falloff=0.000002): fullrebuild = self.configuration.has_key("AmbientOcclusion") == False newconfig = FilterConfig() newconfig.numsamples = numsamples newconfig.radius = radius newconfig.amount = amount newconfig.strength = strength newconfig.falloff = falloff self.configuration["AmbientOcclusion"] = newconfig return self.reconfigure(fullrebuild, "AmbientOcclusion") def delAmbientOcclusion(self): if self.configuration.has_key("AmbientOcclusion"): del self.configuration["AmbientOcclusion"] return self.reconfigure(True, "AmbientOcclusion") return True
class CommonFilters: """ Class CommonFilters implements certain common image postprocessing filters. The constructor requires a filter builder as a parameter. """ def __init__(self, win, cam): self.manager = FilterManager(win, cam) self.configuration = {} self.task = None self.cleanup() def loadShader(self, name): fn = os.path.join(os.path.abspath(os.path.dirname(__file__)), name) fn = Filename.fromOsSpecific(fn) fn.makeTrueCase() return Shader.load(fn) def cleanup(self): self.manager.cleanup() self.textures = {} self.finalQuad = None self.bloom = [] self.blur = [] self.ssao = [] if self.task != None: taskMgr.remove(self.task) self.task = None def reconfigure(self, fullrebuild, changed): """ Reconfigure is called whenever any configuration change is made. """ configuration = self.configuration if (fullrebuild): self.cleanup() if (len(configuration) == 0): return auxbits = 0 needtex = {} needtex["color"] = True if (configuration.has_key("CartoonInk")): needtex["aux"] = True auxbits |= AuxBitplaneAttrib.ABOAuxNormal if (configuration.has_key("AmbientOcclusion")): needtex["depth"] = True needtex["ssao0"] = True needtex["ssao1"] = True needtex["ssao2"] = True needtex["aux"] = True auxbits |= AuxBitplaneAttrib.ABOAuxNormal if (configuration.has_key("BlurSharpen")): needtex["blur0"] = True needtex["blur1"] = True if (configuration.has_key("Bloom")): needtex["bloom0"] = True needtex["bloom1"] = True needtex["bloom2"] = True needtex["bloom3"] = True auxbits |= AuxBitplaneAttrib.ABOGlow if (configuration.has_key("ViewGlow")): auxbits |= AuxBitplaneAttrib.ABOGlow for tex in needtex: self.textures[tex] = Texture("scene-" + tex) self.textures[tex].setWrapU(Texture.WMClamp) self.textures[tex].setWrapV(Texture.WMClamp) needtexpix = True self.finalQuad = self.manager.renderSceneInto( textures=self.textures, auxbits=auxbits) if (self.finalQuad == None): self.cleanup() return False if (configuration.has_key("BlurSharpen")): blur0 = self.textures["blur0"] blur1 = self.textures["blur1"] self.blur.append( self.manager.renderQuadInto(colortex=blur0, div=2)) self.blur.append(self.manager.renderQuadInto(colortex=blur1)) self.blur[0].setShaderInput("src", self.textures["color"]) self.blur[0].setShader(self.loadShader("filter-blurx.sha")) self.blur[1].setShaderInput("src", blur0) self.blur[1].setShader(self.loadShader("filter-blury.sha")) if (configuration.has_key("AmbientOcclusion")): ssao0 = self.textures["ssao0"] ssao1 = self.textures["ssao1"] ssao2 = self.textures["ssao2"] self.ssao.append(self.manager.renderQuadInto(colortex=ssao0)) self.ssao.append( self.manager.renderQuadInto(colortex=ssao1, div=2)) self.ssao.append(self.manager.renderQuadInto(colortex=ssao2)) self.ssao[0].setShaderInput("depth", self.textures["depth"]) self.ssao[0].setShaderInput("normal", self.textures["aux"]) self.ssao[0].setShaderInput( "random", loader.loadTexture("maps/random.rgb")) self.ssao[0].setShader(self.loadShader("filter-ssao.sha")) self.ssao[1].setShaderInput("src", ssao0) self.ssao[1].setShader(self.loadShader("filter-blurx.sha")) self.ssao[2].setShaderInput("src", ssao1) self.ssao[2].setShader(self.loadShader("filter-blury.sha")) if (configuration.has_key("Bloom")): bloomconf = configuration["Bloom"] bloom0 = self.textures["bloom0"] bloom1 = self.textures["bloom1"] bloom2 = self.textures["bloom2"] bloom3 = self.textures["bloom3"] if (bloomconf.size == "large"): scale = 8 downsampler = "filter-down4.sha" elif (bloomconf.size == "medium"): scale = 4 downsampler = "filter-copy.sha" else: scale = 2 downsampler = "filter-copy.sha" self.bloom.append( self.manager.renderQuadInto(colortex=bloom0, div=2, align=scale)) self.bloom.append( self.manager.renderQuadInto(colortex=bloom1, div=scale, align=scale)) self.bloom.append( self.manager.renderQuadInto(colortex=bloom2, div=scale, align=scale)) self.bloom.append( self.manager.renderQuadInto(colortex=bloom3, div=scale, align=scale)) self.bloom[0].setShaderInput("src", self.textures["color"]) self.bloom[0].setShader(self.loadShader("filter-bloomi.sha")) self.bloom[1].setShaderInput("src", bloom0) self.bloom[1].setShader(self.loadShader(downsampler)) self.bloom[2].setShaderInput("src", bloom1) self.bloom[2].setShader(self.loadShader("filter-bloomx.sha")) self.bloom[3].setShaderInput("src", bloom2) self.bloom[3].setShader(self.loadShader("filter-bloomy.sha")) text = "//Cg\n" text += "void vshader(float4 vtx_position : POSITION,\n" text += " out float4 l_position : POSITION,\n" text += " uniform float4 texpad_txcolor,\n" text += " uniform float4 texpix_txcolor,\n" text += " out float4 l_texcoordC : TEXCOORD0,\n" if (configuration.has_key("CartoonInk")): text += " uniform float4 texpad_txaux,\n" text += " uniform float4 texpix_txaux,\n" text += " out float4 l_texcoordN : TEXCOORD1,\n" if (configuration.has_key("Bloom")): text += " uniform float4 texpad_txbloom3,\n" text += " out float4 l_texcoordB : TEXCOORD2,\n" if (configuration.has_key("BlurSharpen")): text += " uniform float4 texpad_txblur1,\n" text += " out float4 l_texcoordBS : TEXCOORD3,\n" if (configuration.has_key("AmbientOcclusion")): text += " uniform float4 texpad_txssao2,\n" text += " out float4 l_texcoordAO : TEXCOORD4,\n" text += " uniform float4x4 mat_modelproj)\n" text += "{\n" text += " l_position=mul(mat_modelproj, vtx_position);\n" text += " l_texcoordC=(vtx_position.xzxz * texpad_txcolor) + texpad_txcolor;\n" if (configuration.has_key("CartoonInk")): text += " l_texcoordN=(vtx_position.xzxz * texpad_txaux) + texpad_txaux;\n" if (configuration.has_key("Bloom")): text += " l_texcoordB=(vtx_position.xzxz * texpad_txbloom3) + texpad_txbloom3;\n" if (configuration.has_key("BlurSharpen")): text += " l_texcoordBS=(vtx_position.xzxz * texpad_txblur1) + texpad_txblur1;\n" if (configuration.has_key("AmbientOcclusion")): text += " l_texcoordAO=(vtx_position.xzxz * texpad_txssao2) + texpad_txssao2;\n" if (configuration.has_key("HalfPixelShift")): text += " l_texcoordC+=texpix_txcolor*0.5;\n" if (configuration.has_key("CartoonInk")): text += " l_texcoordN+=texpix_txaux*0.5;\n" text += "}\n" text += "void fshader(\n" text += "float4 l_texcoordC : TEXCOORD0,\n" text += "uniform float4 texpix_txcolor,\n" if (configuration.has_key("CartoonInk")): text += "float4 l_texcoordN : TEXCOORD1,\n" text += "uniform float4 texpix_txaux,\n" if (configuration.has_key("Bloom")): text += "float4 l_texcoordB : TEXCOORD2,\n" if (configuration.has_key("BlurSharpen")): text += "float4 l_texcoordBS : TEXCOORD3,\n" text += "uniform float4 k_blurval,\n" if (configuration.has_key("AmbientOcclusion")): text += "float4 l_texcoordAO : TEXCOORD4,\n" for key in self.textures: text += "uniform sampler2D k_tx" + key + ",\n" if (configuration.has_key("CartoonInk")): text += "uniform float4 k_cartoonseparation,\n" if (configuration.has_key("VolumetricLighting")): text += "uniform float4 k_casterpos,\n" text += "uniform float4 k_vlparams,\n" text += "out float4 o_color : COLOR)\n" text += "{\n" text += " o_color = tex2D(k_txcolor, l_texcoordC.xy);\n" if (configuration.has_key("CartoonInk")): text += CARTOON_BODY if (configuration.has_key("AmbientOcclusion")): text += "o_color *= tex2D(k_txssao2, l_texcoordAO.xy).r;\n" if (configuration.has_key("BlurSharpen")): text += " o_color = lerp(tex2D(k_txblur1, l_texcoordBS.xy), o_color, k_blurval.x);\n" if (configuration.has_key("Bloom")): text += "o_color = saturate(o_color);\n" text += "float4 bloom = 0.5*tex2D(k_txbloom3, l_texcoordB.xy);\n" text += "o_color = 1-((1-bloom)*(1-o_color));\n" if (configuration.has_key("ViewGlow")): text += "o_color.r = o_color.a;\n" if (configuration.has_key("VolumetricLighting")): text += "float decay = 1.0f;\n" text += "float2 curcoord = l_texcoordC.xy;\n" text += "float2 lightdir = curcoord - k_casterpos.xy;\n" text += "lightdir *= k_vlparams.x;\n" text += "half4 sample = tex2D(k_txcolor, curcoord);\n" text += "float3 vlcolor = sample.rgb * sample.a;\n" text += "for (int i = 0; i < %s; i++) {\n" % int( configuration["VolumetricLighting"].numsamples) text += " curcoord -= lightdir;\n" text += " sample = tex2D(k_txcolor, curcoord);\n" text += " sample *= sample.a * decay;//*weight\n" text += " vlcolor += sample.rgb;\n" text += " decay *= k_vlparams.y;\n" text += "}\n" text += "o_color += float4(vlcolor * k_vlparams.z, 1);\n" if (configuration.has_key("Inverted")): text += "o_color = float4(1, 1, 1, 1) - o_color;\n" text += "}\n" self.finalQuad.setShader(Shader.make(text)) for tex in self.textures: self.finalQuad.setShaderInput("tx" + tex, self.textures[tex]) self.task = taskMgr.add(self.update, "common-filters-update") if (changed == "CartoonInk") or fullrebuild: if (configuration.has_key("CartoonInk")): separation = configuration["CartoonInk"] self.finalQuad.setShaderInput( "cartoonseparation", Vec4(separation, 0, separation, 0)) if (changed == "BlurSharpen") or fullrebuild: if (configuration.has_key("BlurSharpen")): blurval = configuration["BlurSharpen"] self.finalQuad.setShaderInput( "blurval", Vec4(blurval, blurval, blurval, blurval)) if (changed == "Bloom") or fullrebuild: if (configuration.has_key("Bloom")): bloomconf = configuration["Bloom"] intensity = bloomconf.intensity * 3.0 self.bloom[0].setShaderInput("blend", bloomconf.blendx, bloomconf.blendy, bloomconf.blendz, bloomconf.blendw * 2.0) self.bloom[0].setShaderInput( "trigger", bloomconf.mintrigger, 1.0 / (bloomconf.maxtrigger - bloomconf.mintrigger), 0.0, 0.0) self.bloom[0].setShaderInput("desat", bloomconf.desat) self.bloom[3].setShaderInput("intensity", intensity, intensity, intensity, intensity) if (changed == "VolumetricLighting") or fullrebuild: if (configuration.has_key("VolumetricLighting")): config = configuration["VolumetricLighting"] tcparam = config.density / float(config.numsamples) self.finalQuad.setShaderInput("vlparams", tcparam, config.decay, config.exposure, 0.0) if (changed == "AmbientOcclusion") or fullrebuild: if (configuration.has_key("AmbientOcclusion")): config = configuration["AmbientOcclusion"] self.ssao[0].setShaderInput( "params1", config.numsamples, -float(config.amount) / config.numsamples, config.radius, 0) self.ssao[0].setShaderInput("params2", config.strength, config.falloff, 0, 0) self.update() return True def update(self, task=None): """Updates the shader inputs that need to be updated every frame. Normally, you shouldn't call this, it's being called in a task.""" if self.configuration.has_key("VolumetricLighting"): caster = self.configuration["VolumetricLighting"].caster casterpos = Point2() self.manager.camera.node().getLens().project( caster.getPos(self.manager.camera), casterpos) self.finalQuad.setShaderInput( "casterpos", Vec4(casterpos.getX() * 0.5 + 0.5, (casterpos.getY() * 0.5 + 0.5), 0, 0)) if task != None: return task.cont def setCartoonInk(self, separation=1): fullrebuild = (self.configuration.has_key("CartoonInk") == False) self.configuration["CartoonInk"] = separation return self.reconfigure(fullrebuild, "CartoonInk") def delCartoonInk(self): if (self.configuration.has_key("CartoonInk")): del self.configuration["CartoonInk"] return self.reconfigure(True, "CartoonInk") return True def setBloom(self, blend=(0.3, 0.4, 0.3, 0.0), mintrigger=0.6, maxtrigger=1.0, desat=0.6, intensity=1.0, size="medium"): if (size == 0): size = "off" elif (size == 1): size = "small" elif (size == 2): size = "medium" elif (size == 3): size = "large" if (size == "off"): self.delBloom() return if (maxtrigger == None): maxtrigger = mintrigger + 0.8 oldconfig = self.configuration.get("Bloom", None) fullrebuild = True if (oldconfig) and (oldconfig.size == size): fullrebuild = False newconfig = FilterConfig() (newconfig.blendx, newconfig.blendy, newconfig.blendz, newconfig.blendw) = blend newconfig.maxtrigger = maxtrigger newconfig.mintrigger = mintrigger newconfig.desat = desat newconfig.intensity = intensity newconfig.size = size self.configuration["Bloom"] = newconfig return self.reconfigure(fullrebuild, "Bloom") def delBloom(self): if (self.configuration.has_key("Bloom")): del self.configuration["Bloom"] return self.reconfigure(True, "Bloom") return True def setHalfPixelShift(self): fullrebuild = (self.configuration.has_key("HalfPixelShift") == False) self.configuration["HalfPixelShift"] = 1 return self.reconfigure(fullrebuild, "HalfPixelShift") def delHalfPixelShift(self): if (self.configuration.has_key("HalfPixelShift")): del self.configuration["HalfPixelShift"] return self.reconfigure(True, "HalfPixelShift") return True def setViewGlow(self): fullrebuild = (self.configuration.has_key("ViewGlow") == False) self.configuration["ViewGlow"] = 1 return self.reconfigure(fullrebuild, "ViewGlow") def delViewGlow(self): if (self.configuration.has_key("ViewGlow")): del self.configuration["ViewGlow"] return self.reconfigure(True, "ViewGlow") return True def setInverted(self): fullrebuild = (self.configuration.has_key("Inverted") == False) self.configuration["Inverted"] = 1 return self.reconfigure(fullrebuild, "Inverted") def delInverted(self): if (self.configuration.has_key("Inverted")): del self.configuration["Inverted"] return self.reconfigure(True, "Inverted") return True def setVolumetricLighting(self, caster, numsamples=32, density=5.0, decay=0.1, exposure=0.1): oldconfig = self.configuration.get("VolumetricLighting", None) fullrebuild = True if (oldconfig) and (oldconfig.caster == caster): fullrebuild = False newconfig = FilterConfig() newconfig.caster = caster newconfig.numsamples = int(numsamples) newconfig.density = density newconfig.decay = decay newconfig.exposure = exposure self.configuration["VolumetricLighting"] = newconfig return self.reconfigure(fullrebuild, "VolumetricLighting") def delVolumetricLighting(self): if (self.configuration.has_key("VolumetricLighting")): del self.configuration["VolumetricLighting"] return self.reconfigure(True, "VolumetricLighting") return True def setBlurSharpen(self, amount=0.0): """Enables the blur/sharpen filter. If the 'amount' parameter is 1.0, it will not have effect. A value of 0.0 means fully blurred, and a value higher than 1.0 sharpens the image.""" fullrebuild = (self.configuration.has_key("BlurSharpen") == False) self.configuration["BlurSharpen"] = amount return self.reconfigure(fullrebuild, "BlurSharpen") def delBlurSharpen(self): if (self.configuration.has_key("BlurSharpen")): del self.configuration["BlurSharpen"] return self.reconfigure(True, "BlurSharpen") return True def setAmbientOcclusion(self, numsamples=16, radius=0.05, amount=2.0, strength=0.01, falloff=0.000002): fullrebuild = (self.configuration.has_key("AmbientOcclusion") == False) newconfig = FilterConfig() newconfig.numsamples = numsamples newconfig.radius = radius newconfig.amount = amount newconfig.strength = strength newconfig.falloff = falloff self.configuration["AmbientOcclusion"] = newconfig return self.reconfigure(fullrebuild, "AmbientOcclusion") def delAmbientOcclusion(self): if (self.configuration.has_key("AmbientOcclusion")): del self.configuration["AmbientOcclusion"] return self.reconfigure(True, "AmbientOcclusion") return True
class CommonFilters: """ Class CommonFilters implements certain common image postprocessing filters. The constructor requires a filter builder as a parameter. """ def __init__(self, win, cam): self.manager = FilterManager(win, cam) self.configuration = {} self.task = None self.cleanup() def loadShader(self, name): fn = os.path.join(os.path.abspath(os.path.dirname(__file__)), name) fn = Filename.fromOsSpecific(fn) fn.makeTrueCase() return Shader.load(fn) def cleanup(self): self.manager.cleanup() self.textures = {} self.finalQuad = None self.bloom = [] self.blur = [] self.ssao = [] if self.task != None: taskMgr.remove(self.task) self.task = None def reconfigure(self, fullrebuild, changed): """ Reconfigure is called whenever any configuration change is made. """ configuration = self.configuration if (fullrebuild): self.cleanup() if (len(configuration) == 0): return auxbits = 0 needtex = set(["color"]) needtexcoord = set(["color"]) if ("CartoonInk" in configuration): needtex.add("aux") auxbits |= AuxBitplaneAttrib.ABOAuxNormal needtexcoord.add("aux") if ("AmbientOcclusion" in configuration): needtex.add("depth") needtex.add("ssao0") needtex.add("ssao1") needtex.add("ssao2") needtex.add("aux") auxbits |= AuxBitplaneAttrib.ABOAuxNormal needtexcoord.add("ssao2") if ("BlurSharpen" in configuration): needtex.add("blur0") needtex.add("blur1") needtexcoord.add("blur1") if ("Bloom" in configuration): needtex.add("bloom0") needtex.add("bloom1") needtex.add("bloom2") needtex.add("bloom3") auxbits |= AuxBitplaneAttrib.ABOGlow needtexcoord.add("bloom3") if ("ViewGlow" in configuration): auxbits |= AuxBitplaneAttrib.ABOGlow if ("VolumetricLighting" in configuration): needtex.add(configuration["VolumetricLighting"].source) for tex in needtex: self.textures[tex] = Texture("scene-" + tex) self.textures[tex].setWrapU(Texture.WMClamp) self.textures[tex].setWrapV(Texture.WMClamp) self.finalQuad = self.manager.renderSceneInto(textures = self.textures, auxbits=auxbits) if (self.finalQuad == None): self.cleanup() return False if ("BlurSharpen" in configuration): blur0=self.textures["blur0"] blur1=self.textures["blur1"] self.blur.append(self.manager.renderQuadInto(colortex=blur0,div=2)) self.blur.append(self.manager.renderQuadInto(colortex=blur1)) self.blur[0].setShaderInput("src", self.textures["color"]) self.blur[0].setShader(self.loadShader("filter-blurx.sha")) self.blur[1].setShaderInput("src", blur0) self.blur[1].setShader(self.loadShader("filter-blury.sha")) if ("AmbientOcclusion" in configuration): ssao0=self.textures["ssao0"] ssao1=self.textures["ssao1"] ssao2=self.textures["ssao2"] self.ssao.append(self.manager.renderQuadInto(colortex=ssao0)) self.ssao.append(self.manager.renderQuadInto(colortex=ssao1,div=2)) self.ssao.append(self.manager.renderQuadInto(colortex=ssao2)) self.ssao[0].setShaderInput("depth", self.textures["depth"]) self.ssao[0].setShaderInput("normal", self.textures["aux"]) self.ssao[0].setShaderInput("random", loader.loadTexture("maps/random.rgb")) self.ssao[0].setShader(Shader.make(SSAO_BODY % configuration["AmbientOcclusion"].numsamples, Shader.SL_Cg)) self.ssao[1].setShaderInput("src", ssao0) self.ssao[1].setShader(self.loadShader("filter-blurx.sha")) self.ssao[2].setShaderInput("src", ssao1) self.ssao[2].setShader(self.loadShader("filter-blury.sha")) if ("Bloom" in configuration): bloomconf = configuration["Bloom"] bloom0=self.textures["bloom0"] bloom1=self.textures["bloom1"] bloom2=self.textures["bloom2"] bloom3=self.textures["bloom3"] if (bloomconf.size == "large"): scale=8 downsampler="filter-down4.sha" elif (bloomconf.size == "medium"): scale=4 downsampler="filter-copy.sha" else: scale=2 downsampler="filter-copy.sha" self.bloom.append(self.manager.renderQuadInto(colortex=bloom0, div=2, align=scale)) self.bloom.append(self.manager.renderQuadInto(colortex=bloom1, div=scale, align=scale)) self.bloom.append(self.manager.renderQuadInto(colortex=bloom2, div=scale, align=scale)) self.bloom.append(self.manager.renderQuadInto(colortex=bloom3, div=scale, align=scale)) self.bloom[0].setShaderInput("src", self.textures["color"]) self.bloom[0].setShader(self.loadShader("filter-bloomi.sha")) self.bloom[1].setShaderInput("src", bloom0) self.bloom[1].setShader(self.loadShader(downsampler)) self.bloom[2].setShaderInput("src", bloom1) self.bloom[2].setShader(self.loadShader("filter-bloomx.sha")) self.bloom[3].setShaderInput("src", bloom2) self.bloom[3].setShader(self.loadShader("filter-bloomy.sha")) texcoords = {} texcoordPadding = {} for tex in needtexcoord: if self.textures[tex].getAutoTextureScale() != ATSNone or \ "HalfPixelShift" in configuration: texcoords[tex] = "l_texcoord_" + tex texcoordPadding["l_texcoord_" + tex] = tex else: # Share unpadded texture coordinates. texcoords[tex] = "l_texcoord" texcoordPadding["l_texcoord"] = None texcoordSets = list(enumerate(texcoordPadding.keys())) text = "//Cg\n" text += "void vshader(float4 vtx_position : POSITION,\n" text += " out float4 l_position : POSITION,\n" for texcoord, padTex in texcoordPadding.items(): if padTex is not None: text += " uniform float4 texpad_tx%s,\n" % (padTex) if ("HalfPixelShift" in configuration): text += " uniform float4 texpix_tx%s,\n" % (padTex) for i, name in texcoordSets: text += " out float2 %s : TEXCOORD%d,\n" % (name, i) text += " uniform float4x4 mat_modelproj)\n" text += "{\n" text += " l_position = mul(mat_modelproj, vtx_position);\n" for texcoord, padTex in texcoordPadding.items(): if padTex is None: text += " %s = vtx_position.xz * float2(0.5, 0.5) + float2(0.5, 0.5);\n" % (texcoord) else: text += " %s = (vtx_position.xz * texpad_tx%s.xy) + texpad_tx%s.xy;\n" % (texcoord, padTex, padTex) if ("HalfPixelShift" in configuration): text += " %s += texpix_tx%s.xy * 0.5;\n" % (texcoord, padTex) text += "}\n" text += "void fshader(\n" for i, name in texcoordSets: text += " float2 %s : TEXCOORD%d,\n" % (name, i) for key in self.textures: text += " uniform sampler2D k_tx" + key + ",\n" if ("CartoonInk" in configuration): text += " uniform float4 k_cartoonseparation,\n" text += " uniform float4 k_cartooncolor,\n" text += " uniform float4 texpix_txaux,\n" if ("BlurSharpen" in configuration): text += " uniform float4 k_blurval,\n" if ("VolumetricLighting" in configuration): text += " uniform float4 k_casterpos,\n" text += " uniform float4 k_vlparams,\n" text += " out float4 o_color : COLOR)\n" text += "{\n" text += " o_color = tex2D(k_txcolor, %s);\n" % (texcoords["color"]) if ("CartoonInk" in configuration): text += CARTOON_BODY % {"texcoord" : texcoords["aux"]} if ("AmbientOcclusion" in configuration): text += " o_color *= tex2D(k_txssao2, %s).r;\n" % (texcoords["ssao2"]) if ("BlurSharpen" in configuration): text += " o_color = lerp(tex2D(k_txblur1, %s), o_color, k_blurval.x);\n" % (texcoords["blur1"]) if ("Bloom" in configuration): text += " o_color = saturate(o_color);\n"; text += " float4 bloom = 0.5 * tex2D(k_txbloom3, %s);\n" % (texcoords["bloom3"]) text += " o_color = 1-((1-bloom)*(1-o_color));\n" if ("ViewGlow" in configuration): text += " o_color.r = o_color.a;\n" if ("VolumetricLighting" in configuration): text += " float decay = 1.0f;\n" text += " float2 curcoord = %s;\n" % (texcoords["color"]) text += " float2 lightdir = curcoord - k_casterpos.xy;\n" text += " lightdir *= k_vlparams.x;\n" text += " half4 sample = tex2D(k_txcolor, curcoord);\n" text += " float3 vlcolor = sample.rgb * sample.a;\n" text += " for (int i = 0; i < %s; i++) {\n" % (int(configuration["VolumetricLighting"].numsamples)) text += " curcoord -= lightdir;\n" text += " sample = tex2D(k_tx%s, curcoord);\n" % (configuration["VolumetricLighting"].source) text += " sample *= sample.a * decay;//*weight\n" text += " vlcolor += sample.rgb;\n" text += " decay *= k_vlparams.y;\n" text += " }\n" text += " o_color += float4(vlcolor * k_vlparams.z, 1);\n" if ("GammaAdjust" in configuration): gamma = configuration["GammaAdjust"] if gamma == 0.5: text += " o_color.rgb = sqrt(o_color.rgb);\n" elif gamma == 2.0: text += " o_color.rgb *= o_color.rgb;\n" elif gamma != 1.0: text += " o_color.rgb = pow(o_color.rgb, %ff);\n" % (gamma) if ("Inverted" in configuration): text += " o_color = float4(1, 1, 1, 1) - o_color;\n" text += "}\n" self.finalQuad.setShader(Shader.make(text, Shader.SL_Cg)) for tex in self.textures: self.finalQuad.setShaderInput("tx"+tex, self.textures[tex]) self.task = taskMgr.add(self.update, "common-filters-update") if (changed == "CartoonInk") or fullrebuild: if ("CartoonInk" in configuration): c = configuration["CartoonInk"] self.finalQuad.setShaderInput("cartoonseparation", LVecBase4(c.separation, 0, c.separation, 0)) self.finalQuad.setShaderInput("cartooncolor", c.color) if (changed == "BlurSharpen") or fullrebuild: if ("BlurSharpen" in configuration): blurval = configuration["BlurSharpen"] self.finalQuad.setShaderInput("blurval", LVecBase4(blurval, blurval, blurval, blurval)) if (changed == "Bloom") or fullrebuild: if ("Bloom" in configuration): bloomconf = configuration["Bloom"] intensity = bloomconf.intensity * 3.0 self.bloom[0].setShaderInput("blend", bloomconf.blendx, bloomconf.blendy, bloomconf.blendz, bloomconf.blendw * 2.0) self.bloom[0].setShaderInput("trigger", bloomconf.mintrigger, 1.0/(bloomconf.maxtrigger-bloomconf.mintrigger), 0.0, 0.0) self.bloom[0].setShaderInput("desat", bloomconf.desat) self.bloom[3].setShaderInput("intensity", intensity, intensity, intensity, intensity) if (changed == "VolumetricLighting") or fullrebuild: if ("VolumetricLighting" in configuration): config = configuration["VolumetricLighting"] tcparam = config.density / float(config.numsamples) self.finalQuad.setShaderInput("vlparams", tcparam, config.decay, config.exposure, 0.0) if (changed == "AmbientOcclusion") or fullrebuild: if ("AmbientOcclusion" in configuration): config = configuration["AmbientOcclusion"] self.ssao[0].setShaderInput("params1", config.numsamples, -float(config.amount) / config.numsamples, config.radius, 0) self.ssao[0].setShaderInput("params2", config.strength, config.falloff, 0, 0) self.update() return True def update(self, task = None): """Updates the shader inputs that need to be updated every frame. Normally, you shouldn't call this, it's being called in a task.""" if "VolumetricLighting" in self.configuration: caster = self.configuration["VolumetricLighting"].caster casterpos = LPoint2() self.manager.camera.node().getLens().project(caster.getPos(self.manager.camera), casterpos) self.finalQuad.setShaderInput("casterpos", LVecBase4(casterpos.getX() * 0.5 + 0.5, (casterpos.getY() * 0.5 + 0.5), 0, 0)) if task != None: return task.cont def setCartoonInk(self, separation=1, color=(0, 0, 0, 1)): fullrebuild = (("CartoonInk" in self.configuration) == False) newconfig = FilterConfig() newconfig.separation = separation newconfig.color = color self.configuration["CartoonInk"] = newconfig return self.reconfigure(fullrebuild, "CartoonInk") def delCartoonInk(self): if ("CartoonInk" in self.configuration): del self.configuration["CartoonInk"] return self.reconfigure(True, "CartoonInk") return True def setBloom(self, blend=(0.3,0.4,0.3,0.0), mintrigger=0.6, maxtrigger=1.0, desat=0.6, intensity=1.0, size="medium"): if (size==0): size="off" elif (size==1): size="small" elif (size==2): size="medium" elif (size==3): size="large" if (size=="off"): self.delBloom() return if (maxtrigger==None): maxtrigger=mintrigger+0.8 oldconfig = self.configuration.get("Bloom", None) fullrebuild = True if (oldconfig) and (oldconfig.size == size): fullrebuild = False newconfig = FilterConfig() (newconfig.blendx, newconfig.blendy, newconfig.blendz, newconfig.blendw) = blend newconfig.maxtrigger = maxtrigger newconfig.mintrigger = mintrigger newconfig.desat = desat newconfig.intensity = intensity newconfig.size = size self.configuration["Bloom"] = newconfig return self.reconfigure(fullrebuild, "Bloom") def delBloom(self): if ("Bloom" in self.configuration): del self.configuration["Bloom"] return self.reconfigure(True, "Bloom") return True def setHalfPixelShift(self): fullrebuild = (("HalfPixelShift" in self.configuration) == False) self.configuration["HalfPixelShift"] = 1 return self.reconfigure(fullrebuild, "HalfPixelShift") def delHalfPixelShift(self): if ("HalfPixelShift" in self.configuration): del self.configuration["HalfPixelShift"] return self.reconfigure(True, "HalfPixelShift") return True def setViewGlow(self): fullrebuild = (("ViewGlow" in self.configuration) == False) self.configuration["ViewGlow"] = 1 return self.reconfigure(fullrebuild, "ViewGlow") def delViewGlow(self): if ("ViewGlow" in self.configuration): del self.configuration["ViewGlow"] return self.reconfigure(True, "ViewGlow") return True def setInverted(self): fullrebuild = (("Inverted" in self.configuration) == False) self.configuration["Inverted"] = 1 return self.reconfigure(fullrebuild, "Inverted") def delInverted(self): if ("Inverted" in self.configuration): del self.configuration["Inverted"] return self.reconfigure(True, "Inverted") return True def setVolumetricLighting(self, caster, numsamples = 32, density = 5.0, decay = 0.1, exposure = 0.1, source = "color"): oldconfig = self.configuration.get("VolumetricLighting", None) fullrebuild = True if (oldconfig) and (oldconfig.source == source) and (oldconfig.numsamples == int(numsamples)): fullrebuild = False newconfig = FilterConfig() newconfig.caster = caster newconfig.numsamples = int(numsamples) newconfig.density = density newconfig.decay = decay newconfig.exposure = exposure newconfig.source = source self.configuration["VolumetricLighting"] = newconfig return self.reconfigure(fullrebuild, "VolumetricLighting") def delVolumetricLighting(self): if ("VolumetricLighting" in self.configuration): del self.configuration["VolumetricLighting"] return self.reconfigure(True, "VolumetricLighting") return True def setBlurSharpen(self, amount=0.0): """Enables the blur/sharpen filter. If the 'amount' parameter is 1.0, it will not have effect. A value of 0.0 means fully blurred, and a value higher than 1.0 sharpens the image.""" fullrebuild = (("BlurSharpen" in self.configuration) == False) self.configuration["BlurSharpen"] = amount return self.reconfigure(fullrebuild, "BlurSharpen") def delBlurSharpen(self): if ("BlurSharpen" in self.configuration): del self.configuration["BlurSharpen"] return self.reconfigure(True, "BlurSharpen") return True def setAmbientOcclusion(self, numsamples = 16, radius = 0.05, amount = 2.0, strength = 0.01, falloff = 0.000002): fullrebuild = (("AmbientOcclusion" in self.configuration) == False) if (not fullrebuild): fullrebuild = (numsamples != self.configuration["AmbientOcclusion"].numsamples) newconfig = FilterConfig() newconfig.numsamples = numsamples newconfig.radius = radius newconfig.amount = amount newconfig.strength = strength newconfig.falloff = falloff self.configuration["AmbientOcclusion"] = newconfig return self.reconfigure(fullrebuild, "AmbientOcclusion") def delAmbientOcclusion(self): if ("AmbientOcclusion" in self.configuration): del self.configuration["AmbientOcclusion"] return self.reconfigure(True, "AmbientOcclusion") return True def setGammaAdjust(self, gamma): """ Applies additional gamma correction to the image. 1.0 = no correction. """ old_gamma = self.configuration.get("GammaAdjust", 1.0) if old_gamma != gamma: self.configuration["GammaAdjust"] = gamma return self.reconfigure(True, "GammaAdjust") return True def delGammaAdjust(self): if ("GammaAdjust" in self.configuration): old_gamma = self.configuration["GammaAdjust"] del self.configuration["GammaAdjust"] return self.reconfigure((old_gamma != 1.0), "GammaAdjust") return True
if self.auto: self._auto_run() else: self._manual_run() if __name__ == '__main__': print 'Testing FilterManager...' origin_pos = np.array([200, 0, np.pi/2]) origin_cov = np.eye(3) * 3 # Initial Covariance origin_cov[2,2] = 0.02 # Need to call this or gtk will never release locks gobject.threads_init() fm = FilterManager() run_kf = False run_pf = False #run_kf = True run_pf = True if run_kf: fm.add_filter(KalmanFilter.KalmanFilter(origin_pos, origin_cov)) if run_pf: fm.add_filter(ParticleFilter.ParticleFilter(origin_pos, origin_cov)) tg = TestGUI(fm.get_draw()) #tt = TestThread(fm, tg, auto=True) tt = TestThread(fm, tg, auto=False) tt.start() tg.mainloop()
def __init__(self, win, cam): self.manager = FilterManager(win, cam) self.configuration = {} self.cleanup() self.task = taskMgr.add(self.update, "common-filters-update")
def __init__(self, app): gobject.GObject.__init__(self) self.app = app self.blocks = {} self.wcf_uid_list = [] self.chore_settings = {} self.chrono_times = {} self.chrono_day = (datetime.today() - datetime.utcfromtimestamp(0)).days if not os.path.exists(BLOCK_DB): try: os.makedirs(os.path.dirname(BLOCK_DB)) except: pass else: try: db = open(BLOCK_DB, 'rb') p = pickle.load(db) self.blocks = p[0] self.chore_settings = p[1] self.wcf_uid_list = p[2] self.chrono_times = p[3] self.chrono_day = p[4] db.close() except: print "Something wrong unpickling, trying older format (2.31.1)..." # old format (2.31.1) support try: db = open(BLOCK_DB, 'rb') p = pickle.load(db) self.blocks = p[0] self.wcf_uid_list = p[1] self.chrono_times = p[2] self.chrono_day = p[3] db.close() except: print "No success, something just went wrong unpickling" # more old format (2.31.1) support for t in self.chrono_times: announced = False for c in self.chrono_times[t]: if len(self.chrono_times[t] [c].items()) == 2: # 2.31.1 had 2 fields if not announced: print 'Old format (2.31.1) support: adding extra fields to user', t announced = True self.chrono_times[t][c]["extra_time"] = 0 self.chrono_times[t][c]["mercy_count"] = 0 self.chrono_times[t][c]["force_close"] = 0 self.chrono_times[t][c]["last_active"] = -1 self.__next_update_info = None self.usersmanager = UsersManager() if os.name == "nt": self.win32top = Win32Top(self) self.chrono = Chrono(self) self.firewall_filter = FirewallFilter(self) self.filter_manager = FilterManager(self) self.chore_manager = ChoreManager(self) self.webcontent_filter = WebContentFilter(self, app) self.session_filter = SessionFilter(self) gobject.timeout_add(1000, self.__polling_cb)
class CommonFilters: def __init__(self, win, cam): self.manager = FilterManager(win, cam) self.configuration = {} self.task = None self.cleanup() return def loadShader(self, name): fn = os.path.join(os.path.abspath(os.path.dirname(__file__)), name) fn = Filename.fromOsSpecific(fn) fn.makeTrueCase() return Shader.load(fn) def cleanup(self): self.manager.cleanup() self.textures = {} self.finalQuad = None self.bloom = [] self.blur = [] self.ssao = [] if self.task != None: taskMgr.remove(self.task) self.task = None return def reconfigure(self, fullrebuild, changed): configuration = self.configuration if fullrebuild: self.cleanup() if len(configuration) == 0: return auxbits = 0 needtex = set(['color']) needtexcoord = set(['color']) if 'CartoonInk' in configuration: needtex.add('aux') auxbits |= AuxBitplaneAttrib.ABOAuxNormal needtexcoord.add('aux') if 'AmbientOcclusion' in configuration: needtex.add('depth') needtex.add('ssao0') needtex.add('ssao1') needtex.add('ssao2') needtex.add('aux') auxbits |= AuxBitplaneAttrib.ABOAuxNormal needtexcoord.add('ssao2') if 'BlurSharpen' in configuration: needtex.add('blur0') needtex.add('blur1') needtexcoord.add('blur1') if 'Bloom' in configuration: needtex.add('bloom0') needtex.add('bloom1') needtex.add('bloom2') needtex.add('bloom3') auxbits |= AuxBitplaneAttrib.ABOGlow needtexcoord.add('bloom3') if 'ViewGlow' in configuration: auxbits |= AuxBitplaneAttrib.ABOGlow if 'VolumetricLighting' in configuration: needtex.add(configuration['VolumetricLighting'].source) for tex in needtex: self.textures[tex] = Texture('scene-' + tex) self.textures[tex].setWrapU(Texture.WMClamp) self.textures[tex].setWrapV(Texture.WMClamp) self.finalQuad = self.manager.renderSceneInto( textures=self.textures, auxbits=auxbits) if self.finalQuad == None: self.cleanup() return False if 'BlurSharpen' in configuration: blur0 = self.textures['blur0'] blur1 = self.textures['blur1'] self.blur.append( self.manager.renderQuadInto(colortex=blur0, div=2)) self.blur.append(self.manager.renderQuadInto(colortex=blur1)) self.blur[0].setShaderInput('src', self.textures['color']) self.blur[0].setShader(self.loadShader('filter-blurx.sha')) self.blur[1].setShaderInput('src', blur0) self.blur[1].setShader(self.loadShader('filter-blury.sha')) if 'AmbientOcclusion' in configuration: ssao0 = self.textures['ssao0'] ssao1 = self.textures['ssao1'] ssao2 = self.textures['ssao2'] self.ssao.append(self.manager.renderQuadInto(colortex=ssao0)) self.ssao.append( self.manager.renderQuadInto(colortex=ssao1, div=2)) self.ssao.append(self.manager.renderQuadInto(colortex=ssao2)) self.ssao[0].setShaderInput('depth', self.textures['depth']) self.ssao[0].setShaderInput('normal', self.textures['aux']) self.ssao[0].setShaderInput( 'random', loader.loadTexture('maps/random.rgb')) self.ssao[0].setShader( Shader.make( SSAO_BODY % configuration['AmbientOcclusion'].numsamples, Shader.SL_Cg)) self.ssao[1].setShaderInput('src', ssao0) self.ssao[1].setShader(self.loadShader('filter-blurx.sha')) self.ssao[2].setShaderInput('src', ssao1) self.ssao[2].setShader(self.loadShader('filter-blury.sha')) if 'Bloom' in configuration: bloomconf = configuration['Bloom'] bloom0 = self.textures['bloom0'] bloom1 = self.textures['bloom1'] bloom2 = self.textures['bloom2'] bloom3 = self.textures['bloom3'] if bloomconf.size == 'large': scale = 8 downsampler = 'filter-down4.sha' else: if bloomconf.size == 'medium': scale = 4 downsampler = 'filter-copy.sha' else: scale = 2 downsampler = 'filter-copy.sha' self.bloom.append( self.manager.renderQuadInto(colortex=bloom0, div=2, align=scale)) self.bloom.append( self.manager.renderQuadInto(colortex=bloom1, div=scale, align=scale)) self.bloom.append( self.manager.renderQuadInto(colortex=bloom2, div=scale, align=scale)) self.bloom.append( self.manager.renderQuadInto(colortex=bloom3, div=scale, align=scale)) self.bloom[0].setShaderInput('src', self.textures['color']) self.bloom[0].setShader(self.loadShader('filter-bloomi.sha')) self.bloom[1].setShaderInput('src', bloom0) self.bloom[1].setShader(self.loadShader(downsampler)) self.bloom[2].setShaderInput('src', bloom1) self.bloom[2].setShader(self.loadShader('filter-bloomx.sha')) self.bloom[3].setShaderInput('src', bloom2) self.bloom[3].setShader(self.loadShader('filter-bloomy.sha')) texcoords = {} texcoordPadding = {} for tex in needtexcoord: if self.textures[tex].getAutoTextureScale( ) != ATSNone or 'HalfPixelShift' in configuration: texcoords[tex] = 'l_texcoord_' + tex texcoordPadding['l_texcoord_' + tex] = tex else: texcoords[tex] = 'l_texcoord' texcoordPadding['l_texcoord'] = None texcoordSets = list(enumerate(texcoordPadding.keys())) text = '//Cg\n' text += 'void vshader(float4 vtx_position : POSITION,\n' text += ' out float4 l_position : POSITION,\n' for texcoord, padTex in texcoordPadding.items(): if padTex is not None: text += ' uniform float4 texpad_tx%s,\n' % padTex if 'HalfPixelShift' in configuration: text += ' uniform float4 texpix_tx%s,\n' % padTex for i, name in texcoordSets: text += ' out float2 %s : TEXCOORD%d,\n' % (name, i) text += ' uniform float4x4 mat_modelproj)\n' text += '{\n' text += ' l_position = mul(mat_modelproj, vtx_position);\n' for texcoord, padTex in texcoordPadding.items(): if padTex is None: text += ' %s = vtx_position.xz * float2(0.5, 0.5) + float2(0.5, 0.5);\n' % texcoord else: text += ' %s = (vtx_position.xz * texpad_tx%s.xy) + texpad_tx%s.xy;\n' % ( texcoord, padTex, padTex) if 'HalfPixelShift' in configuration: text += ' %s += texpix_tx%s.xy * 0.5;\n' % (texcoord, padTex) text += '}\n' text += 'void fshader(\n' for i, name in texcoordSets: text += ' float2 %s : TEXCOORD%d,\n' % (name, i) for key in self.textures: text += ' uniform sampler2D k_tx' + key + ',\n' if 'CartoonInk' in configuration: text += ' uniform float4 k_cartoonseparation,\n' text += ' uniform float4 k_cartooncolor,\n' text += ' uniform float4 texpix_txaux,\n' if 'BlurSharpen' in configuration: text += ' uniform float4 k_blurval,\n' if 'VolumetricLighting' in configuration: text += ' uniform float4 k_casterpos,\n' text += ' uniform float4 k_vlparams,\n' text += ' out float4 o_color : COLOR)\n' text += '{\n' text += ' o_color = tex2D(k_txcolor, %s);\n' % texcoords['color'] if 'CartoonInk' in configuration: text += CARTOON_BODY % {'texcoord': texcoords['aux']} if 'AmbientOcclusion' in configuration: text += ' o_color *= tex2D(k_txssao2, %s).r;\n' % texcoords[ 'ssao2'] if 'BlurSharpen' in configuration: text += ' o_color = lerp(tex2D(k_txblur1, %s), o_color, k_blurval.x);\n' % texcoords[ 'blur1'] if 'Bloom' in configuration: text += ' o_color = saturate(o_color);\n' text += ' float4 bloom = 0.5 * tex2D(k_txbloom3, %s);\n' % texcoords[ 'bloom3'] text += ' o_color = 1-((1-bloom)*(1-o_color));\n' if 'ViewGlow' in configuration: text += ' o_color.r = o_color.a;\n' if 'VolumetricLighting' in configuration: text += ' float decay = 1.0f;\n' text += ' float2 curcoord = %s;\n' % texcoords['color'] text += ' float2 lightdir = curcoord - k_casterpos.xy;\n' text += ' lightdir *= k_vlparams.x;\n' text += ' half4 sample = tex2D(k_txcolor, curcoord);\n' text += ' float3 vlcolor = sample.rgb * sample.a;\n' text += ' for (int i = 0; i < %s; i++) {\n' % int( configuration['VolumetricLighting'].numsamples) text += ' curcoord -= lightdir;\n' text += ' sample = tex2D(k_tx%s, curcoord);\n' % configuration[ 'VolumetricLighting'].source text += ' sample *= sample.a * decay;//*weight\n' text += ' vlcolor += sample.rgb;\n' text += ' decay *= k_vlparams.y;\n' text += ' }\n' text += ' o_color += float4(vlcolor * k_vlparams.z, 1);\n' if 'GammaAdjust' in configuration: gamma = configuration['GammaAdjust'] if gamma == 0.5: text += ' o_color.rgb = sqrt(o_color.rgb);\n' elif gamma == 2.0: text += ' o_color.rgb *= o_color.rgb;\n' elif gamma != 1.0: text += ' o_color.rgb = pow(o_color.rgb, %ff);\n' % gamma if 'Inverted' in configuration: text += ' o_color = float4(1, 1, 1, 1) - o_color;\n' text += '}\n' self.finalQuad.setShader(Shader.make(text, Shader.SL_Cg)) for tex in self.textures: self.finalQuad.setShaderInput('tx' + tex, self.textures[tex]) self.task = taskMgr.add(self.update, 'common-filters-update') if changed == 'CartoonInk' or fullrebuild: if 'CartoonInk' in configuration: c = configuration['CartoonInk'] self.finalQuad.setShaderInput( 'cartoonseparation', LVecBase4(c.separation, 0, c.separation, 0)) self.finalQuad.setShaderInput('cartooncolor', c.color) if changed == 'BlurSharpen' or fullrebuild: if 'BlurSharpen' in configuration: blurval = configuration['BlurSharpen'] self.finalQuad.setShaderInput( 'blurval', LVecBase4(blurval, blurval, blurval, blurval)) if changed == 'Bloom' or fullrebuild: if 'Bloom' in configuration: bloomconf = configuration['Bloom'] intensity = bloomconf.intensity * 3.0 self.bloom[0].setShaderInput('blend', bloomconf.blendx, bloomconf.blendy, bloomconf.blendz, bloomconf.blendw * 2.0) self.bloom[0].setShaderInput( 'trigger', bloomconf.mintrigger, 1.0 / (bloomconf.maxtrigger - bloomconf.mintrigger), 0.0, 0.0) self.bloom[0].setShaderInput('desat', bloomconf.desat) self.bloom[3].setShaderInput('intensity', intensity, intensity, intensity, intensity) if changed == 'VolumetricLighting' or fullrebuild: if 'VolumetricLighting' in configuration: config = configuration['VolumetricLighting'] tcparam = config.density / float(config.numsamples) self.finalQuad.setShaderInput('vlparams', tcparam, config.decay, config.exposure, 0.0) if changed == 'AmbientOcclusion' or fullrebuild: if 'AmbientOcclusion' in configuration: config = configuration['AmbientOcclusion'] self.ssao[0].setShaderInput( 'params1', config.numsamples, -float(config.amount) / config.numsamples, config.radius, 0) self.ssao[0].setShaderInput('params2', config.strength, config.falloff, 0, 0) self.update() return True def update(self, task=None): if 'VolumetricLighting' in self.configuration: caster = self.configuration['VolumetricLighting'].caster casterpos = LPoint2() self.manager.camera.node().getLens().project( caster.getPos(self.manager.camera), casterpos) self.finalQuad.setShaderInput( 'casterpos', LVecBase4(casterpos.getX() * 0.5 + 0.5, casterpos.getY() * 0.5 + 0.5, 0, 0)) if task != None: return task.cont return def setCartoonInk(self, separation=1, color=(0, 0, 0, 1)): fullrebuild = ('CartoonInk' in self.configuration) == False newconfig = FilterConfig() newconfig.separation = separation newconfig.color = color self.configuration['CartoonInk'] = newconfig return self.reconfigure(fullrebuild, 'CartoonInk') def delCartoonInk(self): if 'CartoonInk' in self.configuration: del self.configuration['CartoonInk'] return self.reconfigure(True, 'CartoonInk') return True def setBloom(self, blend=(0.3, 0.4, 0.3, 0.0), mintrigger=0.6, maxtrigger=1.0, desat=0.6, intensity=1.0, size='medium'): if size == 0: size = 'off' else: if size == 1: size = 'small' else: if size == 2: size = 'medium' else: if size == 3: size = 'large' if size == 'off': self.delBloom() return if maxtrigger == None: maxtrigger = mintrigger + 0.8 oldconfig = self.configuration.get('Bloom', None) fullrebuild = True if oldconfig and oldconfig.size == size: fullrebuild = False newconfig = FilterConfig() newconfig.blendx, newconfig.blendy, newconfig.blendz, newconfig.blendw = blend newconfig.maxtrigger = maxtrigger newconfig.mintrigger = mintrigger newconfig.desat = desat newconfig.intensity = intensity newconfig.size = size self.configuration['Bloom'] = newconfig return self.reconfigure(fullrebuild, 'Bloom') def delBloom(self): if 'Bloom' in self.configuration: del self.configuration['Bloom'] return self.reconfigure(True, 'Bloom') return True def setHalfPixelShift(self): fullrebuild = ('HalfPixelShift' in self.configuration) == False self.configuration['HalfPixelShift'] = 1 return self.reconfigure(fullrebuild, 'HalfPixelShift') def delHalfPixelShift(self): if 'HalfPixelShift' in self.configuration: del self.configuration['HalfPixelShift'] return self.reconfigure(True, 'HalfPixelShift') return True def setViewGlow(self): fullrebuild = ('ViewGlow' in self.configuration) == False self.configuration['ViewGlow'] = 1 return self.reconfigure(fullrebuild, 'ViewGlow') def delViewGlow(self): if 'ViewGlow' in self.configuration: del self.configuration['ViewGlow'] return self.reconfigure(True, 'ViewGlow') return True def setInverted(self): fullrebuild = ('Inverted' in self.configuration) == False self.configuration['Inverted'] = 1 return self.reconfigure(fullrebuild, 'Inverted') def delInverted(self): if 'Inverted' in self.configuration: del self.configuration['Inverted'] return self.reconfigure(True, 'Inverted') return True def setVolumetricLighting(self, caster, numsamples=32, density=5.0, decay=0.1, exposure=0.1, source='color'): oldconfig = self.configuration.get('VolumetricLighting', None) fullrebuild = True if oldconfig and oldconfig.source == source and oldconfig.numsamples == int( numsamples): fullrebuild = False newconfig = FilterConfig() newconfig.caster = caster newconfig.numsamples = int(numsamples) newconfig.density = density newconfig.decay = decay newconfig.exposure = exposure newconfig.source = source self.configuration['VolumetricLighting'] = newconfig return self.reconfigure(fullrebuild, 'VolumetricLighting') def delVolumetricLighting(self): if 'VolumetricLighting' in self.configuration: del self.configuration['VolumetricLighting'] return self.reconfigure(True, 'VolumetricLighting') return True def setBlurSharpen(self, amount=0.0): fullrebuild = ('BlurSharpen' in self.configuration) == False self.configuration['BlurSharpen'] = amount return self.reconfigure(fullrebuild, 'BlurSharpen') def delBlurSharpen(self): if 'BlurSharpen' in self.configuration: del self.configuration['BlurSharpen'] return self.reconfigure(True, 'BlurSharpen') return True def setAmbientOcclusion(self, numsamples=16, radius=0.05, amount=2.0, strength=0.01, falloff=2e-06): fullrebuild = ('AmbientOcclusion' in self.configuration) == False if not fullrebuild: fullrebuild = numsamples != self.configuration[ 'AmbientOcclusion'].numsamples newconfig = FilterConfig() newconfig.numsamples = numsamples newconfig.radius = radius newconfig.amount = amount newconfig.strength = strength newconfig.falloff = falloff self.configuration['AmbientOcclusion'] = newconfig return self.reconfigure(fullrebuild, 'AmbientOcclusion') def delAmbientOcclusion(self): if 'AmbientOcclusion' in self.configuration: del self.configuration['AmbientOcclusion'] return self.reconfigure(True, 'AmbientOcclusion') return True def setGammaAdjust(self, gamma): old_gamma = self.configuration.get('GammaAdjust', 1.0) if old_gamma != gamma: self.configuration['GammaAdjust'] = gamma return self.reconfigure(True, 'GammaAdjust') return True def delGammaAdjust(self): if 'GammaAdjust' in self.configuration: old_gamma = self.configuration['GammaAdjust'] del self.configuration['GammaAdjust'] return self.reconfigure(old_gamma != 1.0, 'GammaAdjust') return True
def __init__(self, win, cam): self.manager = FilterManager(win, cam) self.configuration = {} self.cleanup() self.task = taskMgr.add(self.update, "common-filters-update")
class CommonFilters: """ Class CommonFilters implements certain common image postprocessing filters. The constructor requires a filter builder as a parameter. """ def __init__(self, win, cam): self.manager = FilterManager(win, cam) self.configuration = {} self.cleanup() self.task = taskMgr.add(self.update, "common-filters-update") def loadShader(self, name): fn = os.path.join(PANDA_SHADER_PATH, name) fn = Filename.fromOsSpecific(fn) fn.makeTrueCase() return Shader.load(fn) def cleanup(self): self.manager.cleanup() self.textures = {} self.finalQuad = None self.bloom = [] def reconfigure(self, fullrebuild, changed): """ Reconfigure is called whenever any configuration change is made. """ configuration = self.configuration if (fullrebuild): self.cleanup() if (len(configuration) == 0): return auxbits = 0 needtex = {} needtex["color"] = True if (configuration.has_key("CartoonInk")): needtex["aux"] = True auxbits |= AuxBitplaneAttrib.ABOAuxNormal if (configuration.has_key("Bloom")): needtex["bloom0"] = True needtex["bloom1"] = True needtex["bloom2"] = True needtex["bloom3"] = True auxbits |= AuxBitplaneAttrib.ABOGlow if (configuration.has_key("ViewGlow")): auxbits |= AuxBitplaneAttrib.ABOGlow for tex in needtex: self.textures[tex] = Texture("scene-"+tex) self.textures[tex].setWrapU(Texture.WMClamp) self.textures[tex].setWrapV(Texture.WMClamp) needtexpix = True self.finalQuad = self.manager.renderSceneInto(textures = self.textures, auxbits=auxbits) if (self.finalQuad == None): self.cleanup() return False if (configuration.has_key("Bloom")): bloomconf = configuration["Bloom"] bloom0=self.textures["bloom0"] bloom1=self.textures["bloom1"] bloom2=self.textures["bloom2"] bloom3=self.textures["bloom3"] if (bloomconf.size == "large"): scale=8 downsampler="filter_down4.sha" elif (bloomconf.size == "medium"): scale=4 downsampler="filter_copy.sha" else: scale=2 downsampler="filter_copy.sha" self.bloom.append(self.manager.renderQuadInto(colortex=bloom0, div=2, align=scale)) self.bloom.append(self.manager.renderQuadInto(colortex=bloom1, div=scale, align=scale)) self.bloom.append(self.manager.renderQuadInto(colortex=bloom2, div=scale, align=scale)) self.bloom.append(self.manager.renderQuadInto(colortex=bloom3, div=scale, align=scale)) self.bloom[0].setShaderInput("src", self.textures["color"]) self.bloom[0].setShader(self.loadShader("filter_bloomi.sha")) self.bloom[1].setShaderInput("src", bloom0) self.bloom[1].setShader(self.loadShader(downsampler)) self.bloom[2].setShaderInput("src", bloom1) self.bloom[2].setShader(self.loadShader("filter_bloomx.sha")) self.bloom[3].setShaderInput("src", bloom2) self.bloom[3].setShader(self.loadShader("filter_bloomy.sha")) text = "//Cg\n" text += "void vshader(float4 vtx_position : POSITION,\n" text += " out float4 l_position : POSITION,\n" text += " uniform float4 texpad_txcolor,\n" text += " uniform float4 texpix_txcolor,\n" text += " out float4 l_texcoordC : TEXCOORD0,\n" if (configuration.has_key("CartoonInk")): text += " uniform float4 texpad_txaux,\n" text += " uniform float4 texpix_txaux,\n" text += " out float4 l_texcoordN : TEXCOORD1,\n" if (configuration.has_key("Bloom")): text += " uniform float4 texpad_txbloom3,\n" text += " out float4 l_texcoordB : TEXCOORD2,\n" text += " uniform float4x4 mat_modelproj)\n" text += "{\n" text += " l_position=mul(mat_modelproj, vtx_position);\n" text += " l_texcoordC=(vtx_position.xzxz * texpad_txcolor) + texpad_txcolor;\n" if (configuration.has_key("CartoonInk")): text += " l_texcoordN=(vtx_position.xzxz * texpad_txaux) + texpad_txaux;\n" if (configuration.has_key("Bloom")): text += " l_texcoordB=(vtx_position.xzxz * texpad_txbloom3) + texpad_txbloom3;\n" if (configuration.has_key("HalfPixelShift")): text += " l_texcoordC+=texpix_txcolor*0.5;\n" if (configuration.has_key("CartoonInk")): text += " l_texcoordN+=texpix_txaux*0.5;\n" text += "}\n" text += "void fshader(\n" text += "float4 l_texcoordC : TEXCOORD0,\n" text += "uniform float4 texpix_txcolor,\n" if (configuration.has_key("CartoonInk")): text += "float4 l_texcoordN : TEXCOORD1,\n" text += "uniform float4 texpix_txaux,\n" if (configuration.has_key("Bloom")): text += "float4 l_texcoordB : TEXCOORD2,\n" for key in self.textures: text += "uniform sampler2D k_tx" + key + ",\n" if (configuration.has_key("CartoonInk")): text += "uniform float4 k_cartoonseparation,\n" if (configuration.has_key("VolumetricLighting")): text += "uniform float4 k_casterpos,\n" text += "uniform float4 k_vlparams,\n" text += "out float4 o_color : COLOR)\n" text += "{\n" text += " o_color = tex2D(k_txcolor, l_texcoordC.xy);\n" if (configuration.has_key("CartoonInk")): text += CARTOON_BODY if (configuration.has_key("Bloom")): text += "o_color = saturate(o_color);\n"; text += "float4 bloom = 0.5*tex2D(k_txbloom3, l_texcoordB.xy);\n" text += "o_color = 1-((1-bloom)*(1-o_color));\n" if (configuration.has_key("ViewGlow")): text += "o_color.r = o_color.a;\n" if (configuration.has_key("VolumetricLighting")): text += "float decay = 1.0f;\n" text += "float2 curcoord = l_texcoordC.xy;\n" text += "float2 lightdir = curcoord - k_casterpos.xy;\n" text += "lightdir *= k_vlparams.y;\n" text += "half4 sample = tex2D(k_txcolor, curcoord);\n" text += "float3 vlcolor = sample.rgb * sample.a;\n" text += "for (int i = 0; i < k_vlparams.x; i++) {\n" text += " curcoord -= lightdir;\n" text += " sample = tex2D(k_txcolor, curcoord);\n" text += " sample *= sample.a * decay;//*weight\n" text += " vlcolor += sample.rgb;\n" text += " decay *= k_vlparams.z;\n" text += "}\n" text += "o_color += float4(vlcolor * k_vlparams.w, 1);\n" if (configuration.has_key("Inverted")): text += "o_color = float4(1, 1, 1, 1) - o_color;\n" text += "}\n" self.finalQuad.setShader(Shader.make(text)) for tex in self.textures: self.finalQuad.setShaderInput("tx"+tex, self.textures[tex]) if (changed == "CartoonInk") or fullrebuild: if (configuration.has_key("CartoonInk")): separation = configuration["CartoonInk"] self.finalQuad.setShaderInput("cartoonseparation", Vec4(separation,0,separation,0)) if (changed == "Bloom") or fullrebuild: if (configuration.has_key("Bloom")): bloomconf = configuration["Bloom"] intensity = bloomconf.intensity * 3.0 self.bloom[0].setShaderInput("blend", bloomconf.blendx, bloomconf.blendy, bloomconf.blendz, bloomconf.blendw * 2.0) self.bloom[0].setShaderInput("trigger", bloomconf.mintrigger, 1.0/(bloomconf.maxtrigger-bloomconf.mintrigger), 0.0, 0.0) self.bloom[0].setShaderInput("desat", bloomconf.desat) self.bloom[3].setShaderInput("intensity", intensity, intensity, intensity, intensity) if (changed == "VolumetricLighting") or fullrebuild: if (configuration.has_key("VolumetricLighting")): config = configuration["VolumetricLighting"] tcparam = config.density / float(config.numsamples) self.finalQuad.setShaderInput("vlparams", config.numsamples, tcparam, config.decay, config.exposure) self.update() return True def update(self, task = None): """Updates the shader inputs that need to be updated every frame. Normally, you shouldn't call this, it's being called in a task.""" if self.configuration.has_key("VolumetricLighting"): caster = self.configuration["VolumetricLighting"].caster casterpos = Point2() self.manager.camera.node().getLens().project(caster.getPos(self.manager.camera), casterpos) self.finalQuad.setShaderInput("casterpos", Vec4(casterpos.getX() * 0.5 + 0.5, (casterpos.getY() * 0.5 + 0.5), 0, 0)) if task != None: return task.cont def setCartoonInk(self, separation=1): fullrebuild = (self.configuration.has_key("CartoonInk") == False) self.configuration["CartoonInk"] = separation return self.reconfigure(fullrebuild, "CartoonInk") def delCartoonInk(self): if (self.configuration.has_key("CartoonInk")): del self.configuration["CartoonInk"] return self.reconfigure(True, "CartoonInk") return True def setBloom(self, blend=(0.3,0.4,0.3,0.0), mintrigger=0.6, maxtrigger=1.0, desat=0.6, intensity=1.0, size="medium"): if (size==0): size="off" elif (size==1): size="small" elif (size==2): size="medium" elif (size==3): size="large" if (size=="off"): self.delBloom() return if (maxtrigger==None): maxtrigger=mintrigger+0.8 oldconfig = self.configuration.get("Bloom", None) fullrebuild = True if (oldconfig) and (oldconfig.size == size): fullrebuild = False newconfig = FilterConfig() (newconfig.blendx, newconfig.blendy, newconfig.blendz, newconfig.blendw) = blend newconfig.maxtrigger = maxtrigger newconfig.mintrigger = mintrigger newconfig.desat = desat newconfig.intensity = intensity newconfig.size = size self.configuration["Bloom"] = newconfig return self.reconfigure(fullrebuild, "Bloom") def delBloom(self): if (self.configuration.has_key("Bloom")): del self.configuration["Bloom"] return self.reconfigure(True, "Bloom") return True def setHalfPixelShift(self): fullrebuild = (self.configuration.has_key("HalfPixelShift") == False) self.configuration["HalfPixelShift"] = 1 return self.reconfigure(fullrebuild, "HalfPixelShift") def delHalfPixelShift(self): if (self.configuration.has_key("HalfPixelShift")): del self.configuration["HalfPixelShift"] return self.reconfigure(True, "HalfPixelShift") return True def setViewGlow(self): fullrebuild = (self.configuration.has_key("ViewGlow") == False) self.configuration["ViewGlow"] = 1 return self.reconfigure(fullrebuild, "ViewGlow") def delViewGlow(self): if (self.configuration.has_key("ViewGlow")): del self.configuration["ViewGlow"] return self.reconfigure(True, "ViewGlow") return True def setInverted(self): fullrebuild = (self.configuration.has_key("Inverted") == False) self.configuration["Inverted"] = 1 return self.reconfigure(fullrebuild, "Inverted") def delInverted(self): if (self.configuration.has_key("Inverted")): del self.configuration["Inverted"] return self.reconfigure(True, "Inverted") return True def setVolumetricLighting(self, caster, numsamples = 32, density = 5.0, decay = 0.1, exposure = 0.1): fullrebuild = (self.configuration.has_key("VolumetricLighting") == False) newconfig = FilterConfig() newconfig.caster = caster newconfig.numsamples = numsamples newconfig.density = density newconfig.decay = decay newconfig.exposure = exposure self.configuration["VolumetricLighting"] = newconfig return self.reconfigure(fullrebuild, "VolumetricLighting") def delVolumetricLighting(self): if (self.configuration.has_key("VolumetricLighting")): del self.configuration["VolumetricLighting"] return self.reconfigure(True, "VolumetricLighting") return True