Exemplo n.º 1
0
    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)
Exemplo n.º 2
0
 def __init__(self, win, cam):
     self.manager = FilterManager(win, cam)
     self.configuration = {}
     self.task = None
     self.cleanup()
Exemplo n.º 3
0
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
Exemplo n.º 4
0
 def __init__(self, win, cam):
     self.manager = FilterManager(win, cam)
     self.configuration = {}
     self.task = None
     self.cleanup()
Exemplo n.º 5
0
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
Exemplo n.º 6
0
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
Exemplo n.º 7
0
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
Exemplo n.º 8
0
        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()
Exemplo n.º 9
0
 def __init__(self, win, cam):
     self.manager = FilterManager(win, cam)
     self.configuration = {}
     self.cleanup()
     self.task = taskMgr.add(self.update, "common-filters-update")
Exemplo n.º 10
0
    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
Exemplo n.º 12
0
 def __init__(self, win, cam):
     self.manager = FilterManager(win, cam)
     self.configuration = {}
     self.cleanup()
     self.task = taskMgr.add(self.update, "common-filters-update")
Exemplo n.º 13
0
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