Esempio n. 1
0
class ToontownLUTManager():
    def __init__(self):
        self.manager = FilterManager(base.win, base.cam)

        # Gonna use a Tuple for now
        # This list should be stored somewhere else ultimately, probably like in a globals file
        # [Friendly LUT Name, LUT Filepath]
        self.LUTList = (
            ["Default", "phase_3/luts/def_lut.png"],
            ["LSD", "phase_3/luts/lsd_lut.png"],
            ["Sunset", "phase_3/luts/sunset_lut.png"],
            ["Natural Pop", "phase_3/luts/pop_lut.png"],
            ["Red+Black", "phase_3/luts/2_lut.png"]
        )
        self.vertexShader = "phase_3/shaders/lut-vert.glsl"
        self.fragmentShader = "phase_3/shaders/lut-frag.glsl"
        self.setupLUT(self.LUTList[0][1])

    def setupLUT(self, lut_file):
        colortex = Texture()
        self.quad = self.manager.renderSceneInto(colortex = colortex)
        self.quad.setShader(Shader.load(Shader.SLGLSL, self.vertexShader, self.fragmentShader))
        self.quad.setShaderInput("colortex", colortex)
        lut = loader.loadTexture(lut_file)
        lut.setFormat(Texture.F_rgb16)
        lut.setWrapU(Texture.WMClamp)
        lut.setWrapV(Texture.WMClamp)
        self.quad.setShaderInput("lut", lut)

    def loadTUL(self, lut_file, format = Texture.F_rgb):
        lut = loader.loadTexture(lut_file)
        lut.setFormat(Texture.F_rgb16)
        lut.setWrapU(Texture.WMClamp)
        lut.setWrapV(Texture.WMClamp)
        self.quad.setShaderInput("lut", lut)

    def getLUTS(self):
        return self.LUTList

    def cleanup(self):
        self.manager.cleanup()
Esempio n. 2
0
class Postprocess():
    def __init__(self):
        self.filter_tex = {}
        self.manager = FilterManager(base.win, base.cam)
        self.filters = {}

        self.window_x = float(base.win.getXSize())
        self.window_y = float(base.win.getYSize())

    def reset(self):
        self.manager.cleanup()
        self.filter_tex = {}
        self.manager = FilterManager(base.win, base.cam)
        self.filters = {}
        self.window_x = float(base.win.getXSize())
        self.window_y = float(base.win.getYSize())

    def setupFilters(self, useFxaa=True):
        colorTex = Texture()  #the scene
        colorTex.setWrapU(Texture.WMClamp)
        colorTex.setWrapV(Texture.WMClamp)
        colorTex.setFormat(Texture.F_rgb16)
        auxTex = Texture()  # r=blur, g=shadow, b=?, a=?
        composeTex = Texture(
        )  #the scene(colorTex) blured where auxTex.r>0 and with shadows (blurTex2.r) added
        self.filters = {}
        final_quad = self.manager.renderSceneInto(colortex=colorTex,
                                                  auxtex=auxTex)

        blurTex = Texture()  #1/2 size of the shadows to be blured
        blurTex.setWrapU(Texture.WMClamp)
        blurTex.setWrapV(Texture.WMClamp)
        blurTex2 = Texture()
        blurTex2.setWrapU(Texture.WMClamp)
        blurTex2.setWrapV(Texture.WMClamp)
        glareTex = Texture()
        glareTex.setWrapU(Texture.WMClamp)
        glareTex.setWrapV(Texture.WMClamp)
        flareTex = Texture()
        flareTex.setWrapU(Texture.WMClamp)
        flareTex.setWrapV(Texture.WMClamp)
        flareTex2 = Texture()
        flareTex2.setWrapU(Texture.WMClamp)
        flareTex2.setWrapV(Texture.WMClamp)
        #blurr shadows #1
        interquad0 = self.manager.renderQuadInto(colortex=blurTex, div=8)
        interquad0.setShader(
            Shader.load(Shader.SLGLSL, path + "shaders/blur_v.glsl",
                        path + "shaders/blur_f.glsl"))
        interquad0.setShaderInput("input_map", auxTex)
        interquad0.setShaderInput("sharpness", 0.008)
        self.filters['shadow'] = interquad0
        #blurrscene
        interquad1 = self.manager.renderQuadInto(colortex=blurTex2, div=4)
        interquad1.setShader(
            Shader.load(Shader.SLGLSL, path + "shaders/blur_v.glsl",
                        path + "shaders/blur_f.glsl"))
        interquad1.setShaderInput("input_map", colorTex)
        interquad1.setShaderInput("sharpness", 0.005)
        self.filters['blur'] = interquad1
        #glare
        interquad2 = self.manager.renderQuadInto(colortex=glareTex, div=2)
        interquad2.setShader(
            Shader.load(Shader.SLGLSL, path + "shaders/glare_v.glsl",
                        path + "shaders/glare_f.glsl"))
        interquad2.setShaderInput("auxTex", auxTex)
        interquad2.setShaderInput("colorTex", blurTex2)
        interquad2.setShaderInput("blurTex", blurTex)
        self.filters['glare'] = interquad2
        #lense flare
        interquad3 = self.manager.renderQuadInto(colortex=flareTex, div=2)
        #interquad3.setShader(Shader.load(path+"shaders/lens_flare.sha"))
        #interquad3.setShaderInput("tex0", glareTex)
        interquad3.setShader(
            Shader.load(Shader.SLGLSL, path + "shaders/flare_v.glsl",
                        path + "shaders/flare_f.glsl"))
        interquad3.setShaderInput("glareTex", glareTex)
        self.filters['flare'] = interquad3
        interquad3a = self.manager.renderQuadInto(colortex=flareTex2, div=2)
        interquad3a.setShader(
            Shader.load(Shader.SLGLSL, path + "shaders/blur_v.glsl",
                        path + "shaders/blur_f.glsl"))
        interquad3a.setShaderInput("input_map", flareTex)
        interquad3a.setShaderInput("sharpness", 0.005)
        self.filters['flare2'] = interquad1
        if useFxaa:
            #compose the scene
            interquad4 = self.manager.renderQuadInto(colortex=composeTex)
            interquad4.setShader(
                Shader.load(Shader.SLGLSL, path + "shaders/compose_v.glsl",
                            path + "shaders/compose_f.glsl"))
            interquad4.setShaderInput("flareTex", flareTex2)
            interquad4.setShaderInput("glareTex", glareTex)
            interquad4.setShaderInput("colorTex", colorTex)
            interquad4.setShaderInput("blurTex", blurTex)
            interquad4.setShaderInput("blurTex2", blurTex2)
            interquad4.setShaderInput("auxTex", auxTex)
            interquad4.setShaderInput(
                "noiseTex", loader.loadTexture(path + "data/noise2.png"))
            star_tex = loader.loadTexture(path + "data/star.png")
            star_tex.setWrapU(Texture.WM_mirror_once)
            star_tex.setWrapV(Texture.WM_mirror_once)
            interquad4.setShaderInput("starTex", star_tex)
            interquad4.setShaderInput('time', 0.0)
            interquad4.setShaderInput(
                'screen_size',
                Vec2(float(base.win.getXSize()), float(base.win.getYSize())))
            #fxaa
            final_quad.setShader(
                Shader.load(Shader.SLGLSL, path + "shaders/fxaa_v.glsl",
                            path + "shaders/fxaa_f.glsl"))
            final_quad.setShaderInput("tex0", composeTex)
            final_quad.setShaderInput("rt_w", float(base.win.getXSize()))
            final_quad.setShaderInput("rt_h", float(base.win.getYSize()))
            final_quad.setShaderInput("FXAA_SPAN_MAX", float(8.0))
            final_quad.setShaderInput("FXAA_REDUCE_MUL", float(1.0 / 8.0))
            final_quad.setShaderInput("FXAA_SUBPIX_SHIFT", float(1.0 / 4.0))
            self.filters['fxaa'] = final_quad
        else:
            #compose the scene
            final_quad.setShader(
                Shader.load(Shader.SLGLSL, path + "shaders/compose_v.glsl",
                            path + "shaders/compose_f.glsl"))
            final_quad.setShaderInput("flareTex", flareTex2)
            final_quad.setShaderInput("glareTex", glareTex)
            final_quad.setShaderInput("colorTex", colorTex)
            final_quad.setShaderInput("blurTex", blurTex)
            final_quad.setShaderInput("blurTex2", blurTex2)
            final_quad.setShaderInput("auxTex", auxTex)
            final_quad.setShaderInput(
                "noiseTex", loader.loadTexture(path + "data/noise2.png"))
            star_tex = loader.loadTexture(path + "data/star.png")
            star_tex.setWrapU(Texture.WM_mirror_once)
            star_tex.setWrapV(Texture.WM_mirror_once)
            final_quad.setShaderInput("starTex", star_tex)
            final_quad.setShaderInput('time', 0.0)
            final_quad.setShaderInput(
                'screen_size',
                Vec2(float(base.win.getXSize()), float(base.win.getYSize())))
            self.filters['compose'] = final_quad

    def setupFxaa(self):
        colorTex = Texture()  #the scene
        final_quad = self.manager.renderSceneInto(colortex=colorTex)
        final_quad.setShader(
            Shader.load(Shader.SLGLSL, path + "shaders/fxaa_v.glsl",
                        path + "shaders/fxaa_f.glsl"))
        final_quad.setShaderInput("tex0", colorTex)
        final_quad.setShaderInput("rt_w", float(base.win.getXSize()))
        final_quad.setShaderInput("rt_h", float(base.win.getYSize()))
        final_quad.setShaderInput("FXAA_SPAN_MAX", float(8.0))
        final_quad.setShaderInput("FXAA_REDUCE_MUL", float(1.0 / 8.0))
        final_quad.setShaderInput("FXAA_SUBPIX_SHIFT", float(1.0 / 4.0))
        self.filters['fxaa'] = final_quad

    def update(self):
        x = float(base.win.getXSize())
        y = float(base.win.getYSize())
        if self.filters:
            if 'fxaa' in self.filters:
                self.filters['fxaa'].setShaderInput("rt_w", x)
                self.filters['fxaa'].setShaderInput("rt_h", y)
            if 'compose' in self.filters:
                self.filters['compose'].setShaderInput("screen_size",
                                                       Vec2(x, y))
Esempio n. 3
0
File: filters.py Progetto: wezu/a4p
class Filters():
    def __init__(self):
        self.filter_tex={}
        self.manager=FilterManager(base.win, base.cam)
        self.filters={}

        self.window_x=float(base.win.getXSize())
        self.window_y=float(base.win.getYSize())
        render.setShaderInput('screen_size',Vec2(self.window_x,self.window_y))
        log.debug('Filters: FilterManager started at '+str(base.win.getXSize())+'x'+str(base.win.getYSize()))
        if cfg['use-filters']:
            self.setupFilters()
        elif cfg['use-fxaa']:
            self.setupFxaa()

    def reset(self):
        self.manager.cleanup()
        self.filter_tex={}
        self.manager=FilterManager(base.win, base.cam)
        self.filters={}
        self.window_x=float(base.win.getXSize())
        self.window_y=float(base.win.getYSize())
        if cfg['glsl-blur'] or cfg['glsl-distortion'] or cfg['glsl-flare'] or cfg['glsl-glare'] or cfg['glsl-lut']:
            self.setupFilters()
        elif cfg['use-fxaa']:
            self.setupFxaa()

    def setupFilters(self):
        colorTex = Texture()#the scene
        colorTex.setWrapU(Texture.WMClamp)
        colorTex.setWrapV(Texture.WMClamp)

        auxTex = Texture()
        auxTex.setWrapU(Texture.WMClamp)
        auxTex.setWrapV(Texture.WMClamp)

        composeTex = Texture()
        composeTex.setWrapU(Texture.WMClamp)
        composeTex.setWrapV(Texture.WMClamp)

        self.filters={}
        final_quad = self.manager.renderSceneInto(colortex=colorTex, auxtex=auxTex)

        if cfg['glsl-blur'] or cfg['glsl-distortion'] or cfg['glsl-glare'] or cfg['glsl-flare']:
            if cfg['glsl-blur']:
                #blur scene
                blurTex = Texture()
                blurTex.setWrapU(Texture.WMClamp)
                blurTex.setWrapV(Texture.WMClamp)
                interquad0 = self.manager.renderQuadInto(colortex=blurTex, div=2)
                interquad0.setShader(Shader.load(Shader.SLGLSL, path+'shaders/blur_v.glsl', path+'shaders/blur_f.glsl'))
                interquad0.setShaderInput('input_map', colorTex)
                interquad0.setShaderInput('sharpness', 0.008)
                self.filters['blur']=interquad0
            if cfg['glsl-flare'] or cfg['glsl-glare']:
                #blur aux
                blurTex2 = Texture()
                blurTex2.setWrapU(Texture.WMClamp)
                blurTex2.setWrapV(Texture.WMClamp)
                interquad0 = self.manager.renderQuadInto(colortex=blurTex2, div=2)
                interquad0.setShader(Shader.load(Shader.SLGLSL, path+'shaders/blur_ex_v.glsl', path+'shaders/blur_ex_f.glsl'))
                interquad0.setShaderInput('input_map', auxTex)
                #interquad0.setShaderInput('sharpness', 0.02)
                self.filters['blur_aux']=interquad0

                #glare
                glareTex = Texture()
                glareTex.setWrapU(Texture.WMClamp)
                glareTex.setWrapV(Texture.WMClamp)
                interquad2 = self.manager.renderQuadInto(colortex=glareTex)
                interquad2.setShader(Shader.load(Shader.SLGLSL, path+'shaders/glare_v.glsl', path+'shaders/glare_f.glsl'))
                interquad2.setShaderInput('auxTex', auxTex)
                interquad2.setShaderInput('colorTex', colorTex)
                interquad2.setShaderInput('blurAuxTex', blurTex2)
                self.filters['glare']=interquad2
            if cfg['glsl-flare']:
                #flare
                flareTex = Texture()
                flareTex.setWrapU(Texture.WMClamp)
                flareTex.setWrapV(Texture.WMClamp)
                flareTex2 = Texture()
                flareTex2.setWrapU(Texture.WMClamp)
                flareTex2.setWrapV(Texture.WMClamp)
                #lense flare
                interquad3 = self.manager.renderQuadInto(colortex=flareTex, div=2)
                #interquad3.setShader(Shader.load(path+'shaders/lens_flare.sha'))
                #interquad3.setShaderInput('tex0', glareTex)
                interquad3.setShader(Shader.load(Shader.SLGLSL, path+'shaders/flare_v.glsl', path+'shaders/flare_f.glsl'))
                interquad3.setShaderInput('glareTex', glareTex)
                self.filters['flare']=interquad3
                interquad3a = self.manager.renderQuadInto(colortex=flareTex2, div=2)
                interquad3a.setShader(Shader.load(Shader.SLGLSL, path+'shaders/blur_v.glsl', path+'shaders/blur_f.glsl'))
                interquad3a.setShaderInput('input_map', flareTex)
                interquad3a.setShaderInput('sharpness', 0.008)
                self.filters['flare2']=interquad3a

        if cfg['use-fxaa']:
            #compose the scene
            interquad4 = self.manager.renderQuadInto(colortex=composeTex)
            interquad4.setShader(Shader.load(Shader.SLGLSL, path+'shaders/compose_v.glsl', path+'shaders/compose_f.glsl'))
            interquad4.setShaderInput('colorTex', colorTex)
            interquad4.setShaderInput('auxTex', auxTex)
            if cfg['glsl-blur']:
                dof_tex=loader.loadTexture(path+'data/dof.png')
                dof_tex.setWrapU(Texture.WM_mirror_once)
                dof_tex.setWrapV(Texture.WM_mirror_once)
                interquad4.setShaderInput('dofTex', dof_tex)
                interquad4.setShaderInput('blurTex', blurTex)
            if cfg['glsl-glare']:
                interquad4.setShaderInput('glareTex', glareTex)
            if cfg['glsl-flare']:
                interquad4.setShaderInput('flareTex', flareTex2)
                star_tex=loader.loadTexture(path+'data/'+cfg['flare-tex'])
                star_tex.setWrapU(Texture.WM_mirror_once)
                star_tex.setWrapV(Texture.WM_mirror_once)
                interquad4.setShaderInput('starTex', star_tex)
            if cfg['glsl-lut']:
                lut_tex=loader.loadTexture(path+'data/'+cfg['lut-tex'])
                lut_tex.setFormat(Texture.F_rgb16)
                lut_tex.setWrapU(Texture.WMClamp)
                lut_tex.setWrapV(Texture.WMClamp)
                interquad4.setShaderInput('lut', lut_tex)
            interquad4.setShaderInput('screen_size', Vec2(float(base.win.getXSize()),float(base.win.getYSize())))
            self.filters['compose']=interquad4

            #fxaa
            final_quad.setShader(Shader.load(Shader.SLGLSL, path+'shaders/fxaa_v.glsl', path+'shaders/fxaa_f.glsl'))
            final_quad.setShaderInput('tex0', composeTex)
            final_quad.setShaderInput('rt_w',float(base.win.getXSize()))
            final_quad.setShaderInput('rt_h',float(base.win.getYSize()))
            final_quad.setShaderInput('FXAA_SPAN_MAX' , float(8.0))
            final_quad.setShaderInput('FXAA_REDUCE_MUL', float(1.0/8.0))
            final_quad.setShaderInput('FXAA_SUBPIX_SHIFT', float(1.0/4.0))
            self.filters['fxaa']=final_quad
            log.debug('Filters: Using post-process effects and FXAA')
        else:
            final_quad.setShader(Shader.load(Shader.SLGLSL, path+'shaders/compose_v.glsl', path+'shaders/compose_f.glsl'))
            final_quad.setShaderInput('colorTex', colorTex)
            final_quad.setShaderInput('auxTex', auxTex)
            if cfg['glsl-blur']:
                dof_tex=loader.loadTexture(path+'data/dof.png')
                dof_tex.setWrapU(Texture.WM_mirror_once)
                dof_tex.setWrapV(Texture.WM_mirror_once)
                final_quad.setShaderInput('dofTex', dof_tex)
                final_quad.setShaderInput('blurTex', blurTex)
            if cfg['glsl-glare']:
                final_quad.setShaderInput('glareTex', glareTex)
            if cfg['glsl-flare']:
                final_quad.setShaderInput('flareTex', flareTex2)
                star_tex=loader.loadTexture(path+'data/star.png')
                star_tex.setWrapU(Texture.WM_mirror_once)
                star_tex.setWrapV(Texture.WM_mirror_once)
                final_quad.setShaderInput('starTex', star_tex)
            if cfg['glsl-lut']:
                lut_tex=loader.loadTexture(path+'data/'+cfg['lut-tex'])
                lut_tex.setFormat(Texture.F_rgb16)
                lut_tex.setWrapU(Texture.WMClamp)
                lut_tex.setWrapV(Texture.WMClamp)
                final_quad.setShaderInput('lut', lut_tex)
            final_quad.setShaderInput('screen_size', Vec2(float(base.win.getXSize()),float(base.win.getYSize())))

            self.filters['compose']=final_quad
            log.debug('Filters: Using post-process effects without FXAA')

        for buff in self.manager.buffers:
            buff.setClearValue(GraphicsOutput.RTPAuxRgba0, (0.0, 0.0, 0.0, 1.0))

    def setupFxaa(self):
        colorTex = Texture()#the scene
        final_quad = self.manager.renderSceneInto(colortex=colorTex)
        final_quad.setShader(Shader.load(Shader.SLGLSL, path+'shaders/fxaa_v.glsl', path+'shaders/fxaa_f.glsl'))
        final_quad.setShaderInput('tex0', colorTex)
        final_quad.setShaderInput('rt_w',float(base.win.getXSize()))
        final_quad.setShaderInput('rt_h',float(base.win.getYSize()))
        final_quad.setShaderInput('FXAA_SPAN_MAX' , float(8.0))
        final_quad.setShaderInput('FXAA_REDUCE_MUL', float(1.0/8.0))
        final_quad.setShaderInput('FXAA_SUBPIX_SHIFT', float(1.0/4.0))
        self.filters['fxaa']=final_quad
        log.debug('Filters: Using FXAA only')

    def reloadShaders(self):
        for name, quad in self.filters.items():
            shader=quad.getShader()
            v_shader=shader.getFilename(Shader.ST_vertex)
            f_shader=shader.getFilename(Shader.ST_fragment)
            quad.setShader(Shader.load(Shader.SLGLSL, v_shader,f_shader))
        self.update()

    def update(self):
        x=float(base.win.getXSize())
        y=float(base.win.getYSize())
        render.setShaderInput('screen_size',Vec2(x,y))
        if self.filters:
            if 'fxaa' in self.filters:
                self.filters['fxaa'].setShaderInput('rt_w',x)
                self.filters['fxaa'].setShaderInput('rt_h',y)
            if 'compose' in self.filters:
                self.filters['compose'].setShaderInput('screen_size',Vec2(x,y))
Esempio n. 4
0
class ScreenFilter(object):

    # modes for cycling time
    Time_0_X = 1  # time cycles between 0 and the time period
    Time_0_1 = 2  # time cycles between 0 and 1
    Time_0_2PI = 3  # time cycles between 0 and 2*PI

    # names of predefined shader parameters
    Cos_Time_0_X = 1
    Sin_Time_0_X = 2
    Tan_Time_0_X = 3
    Cos_Time_0_1 = 4
    Sin_Time_0_1 = 5
    Tan_Time_0_1 = 6
    Cos_Time_0_2PI = 7
    Sin_Time_0_2PI = 8
    Tan_Time_0_2PI = 9
    Time = 10
    Time_Period = 11
    '''
    Represents a screen based image effect. Every filter must have a unique name.
    '''
    def __init__(self, name='', game=None):
        self.log = logging.getLogger('pano.screenFilter')
        self.name = name
        self.game = game

        self.postProcess = None
        self.screenQuad = None
        self.enabled = False

        self.shader = None

        # parameters by type
        self.texParams = {}
        self.floatParams = {}
        self.matParams = {}
        self.predefinedParams = {}

        self.nodesRoot = None

        self.time = 0.0
        self.timePeriod = 120.0  # in seconds
        self.timeMode = self.Time_0_X

    def getShader(self):
        '''
        Returns the base name of the shader effect file.  
        '''
        return self.shader

    def setShader(self, shader):
        '''
        Sets the base name of the shader effect file.  
        '''
        differ = self.shader != shader
        self.shader = shader

        if self.isEnabled() and differ:
            self.disable()
            self.enable()

    def enable(self):
        '''
        Enables the filter. It is assumed that after this operation the rendering operation
        has been altered such that the filter effects will be visible. 
        '''
        if self.isEnabled():
            return

        shader = self.game.getResources().loadShader(self.shader)
        if shader is not None:
            self.postProcess = FilterManager(
                self.game.getView().getWindow(),
                self.game.getView().panoRenderer.getCamera())
            self.postProcess.windowEvent(self.game.getView().getWindow(
            ))  # auto resize buffers when window resizes
            tex = Texture()
            self.screenQuad = self.postProcess.renderSceneInto(colortex=tex)
            self.screenQuad.setShader(shader)
            self.screenQuad.setShaderInput("tex", tex)
            self._applyShaderInputs()
            self.enabled = True
        else:
            self.log.error(
                'failed to set screen filter BlackAndWhite because shader %s was not found'
                % self.shader)

    def disable(self):
        '''
        Disables the filter, thereby eliminating the effects of the filter from the rendering
        of the scene. Any graphics resources should also get released here as well because the
        filter might never get enabled again.
        '''
        if not self.enabled: return

        if self.postProcess is not None:
            self._cleanUpShaderInputs()
            self.postProcess.cleanup()
            self.postProcess = None
        self.screenQuad = None
        self.enabled = False

    def update(self, millis):
        '''
        Updates the state of the filter, assuming the given amount of milliseconds have elapsed.
        '''
        #        self.log.debug('updating with %f millis' % millis)
        self.time += millis / 1000.0
        if self.time > self.timePeriod:
            self.time -= self.timePeriod
        self._applyPredefinedInputs()

    def isEnabled(self):
        '''
        Return True if this filter has been enabled or False if otherwise.
        '''
        return self.enabled

    def getTimeMode(self):
        '''
        Returns the time cycling mode.
        '''
        return self.timeMode

    def setTimeMode(self, mode):
        '''
        Sets the time cycling mode.
        '''
        self.timeMode = mode

    def getRenderTarget(self):
        '''
        Returns the screen aligned quad model instance associated with this filter or None if the filter isn't active.
        '''
        return self.screenQuad

    def setTextureParameter(self, name, filename):
        '''
        Sets a named texture parameter which will be accessible to the shader via the input
        uniform sampler2D 'k_<name>'.
        See Panda3D Manual: List of Possible Shader Inputs for more details
        '''
        self.texParams[name] = filename

    def setFloatParameter(self, name, value):
        '''
        Sets a named vector of floats parameter which will be accessible to the shader via the input
        uniform float4 'k_<name>'.
        See Panda3D Manual: List of Possible Shader Inputs for more details
         
        Note: The value parameter must be a tuple or list with at least 4 elements.        
        '''
        self.floatParams[name] = value

    def setMatrixParameter(self, name, mat):
        '''
        Sets a named 4x4 matrix parameter which will be accessible to the shader via the input
        uniform float4x4 'k_<name>'.
        See Panda3D Manual: List of Possible Shader Inputs for more details
         
        Note: The value parameter must be a tuple or list with at least 16 elements.        
        '''
        self.matParams[name] = mat

    def setPredefinedParameter(self, name, value):
        '''
        Sets a named float4 parameter with a predefined semantic and which will be accessible to the shader 
        via the input uniform float4 'k_<name>'.
        See Panda3D Manual: List of Possible Shader Inputs for more details                 
        '''
        self.predefinedParams[name] = value

    def getTextureParameter(self, name):
        '''
        Returns the texture input associated with the given name or None if no such input exists.
        '''
        return self.texParams.get(name)

    def getFloatParameter(self, name):
        '''
        Returns the vector of floats input associated with the given name or None if no such input exists.
        '''
        return self.floatParams.get(name)

    def getMatrixParameter(self, name):
        '''
        Returns the 4x4 matrix input associated with the given name or None if no such input exists.
        '''
        return self.matParams.get(name)

    def getPredefinedParameter(self, name):
        '''
        Returns the float4 input associated with the given name or None if no such input exists.
        '''
        return self.predefinedParams.get(name)

    def _applyShaderInputs(self):
        '''
        Applies the specified texture, vector and matrix shader inputs.
        Note: Matrix inputs are applied to a shader through a NodePath whose local transformation matches the matrix.
        '''
        for param, texName in self.texParams.items():
            tex = self.game.getResources().loadTexture(texName)
            if tex is not None:
                tex.setWrapU(Texture.WMRepeat)
                tex.setWrapV(Texture.WMRepeat)
                self.screenQuad.setShaderInput(param, tex)
            else:
                self.log.error(
                    'Failed to set shader input %s because the texture was not found'
                    % texName)

        for param, val in self.floatParams.items():
            self.screenQuad.setShaderInput(
                param, Vec4(val[0], val[1], val[2], val[3]))

        if self.nodesRoot is None:
            self.nodesRoot = render.attachNewNode('k_matrices')

        for param, val in self.matParams.items():
            np = NodePath()
            np.setName(param + '_transform')
            mat = Mat4()
            for i in range(4):
                mat.setRow(
                    i,
                    Vec4(val[i * 4 + 1], val[i * 4 + 2], val[i * 4 + 3],
                         val[i * 4 + 4]))
            np.setMat(mat)
            np.reparentTo(self.nodesRoot)
            self.screenQuad.setShaderInput(param, np)

        self._applyPredefinedInputs()

    def _applyPredefinedInputs(self):
        for param, val in self.predefinedParams.items():
            if val == self.Time:
                self.screenQuad.setShaderInput(
                    param, Vec4(self._convertTime(self.timeMode), 0, 0, 0))

            elif val == self.Cos_Time_0_X:
                self.screenQuad.setShaderInput(
                    param, Vec4(math.cos(self.time), 0, 0, 0))
            elif val == self.Sin_Time_0_X:
                self.screenQuad.setShaderInput(
                    param, Vec4(math.sin(self.time), 0, 0, 0))
            elif val == self.Tan_Time_0_X:
                self.screenQuad.setShaderInput(
                    param, Vec4(math.tan(self.time), 0, 0, 0))

            elif val == self.Cos_Time_0_1:
                self.screenQuad.setShaderInput(
                    param,
                    Vec4(math.cos(self._convertTime(self.Time_0_1), 0, 0, 0)))
            elif val == self.Sin_Time_0_1:
                self.screenQuad.setShaderInput(
                    param,
                    Vec4(math.sin(self._convertTime(self.Time_0_1), 0, 0, 0)))
            elif val == self.Tan_Time_0_1:
                self.screenQuad.setShaderInput(
                    param,
                    Vec4(math.tan(self._convertTime(self.Time_0_1), 0, 0, 0)))

            elif val == self.Cos_Time_0_2PI:
                self.screenQuad.setShaderInput(
                    param,
                    Vec4(math.cos(self._convertTime(self.Time_0_2PI), 0, 0,
                                  0)))
            elif val == self.Sin_Time_0_2PI:
                self.screenQuad.setShaderInput(
                    param,
                    Vec4(math.sin(self._convertTime(self.Time_0_2PI), 0, 0,
                                  0)))
            elif val == self.Tan_Time_0_2PI:
                self.screenQuad.setShaderInput(
                    param,
                    Vec4(math.tan(self._convertTime(self.Time_0_2PI), 0, 0,
                                  0)))

            elif val == self.Time_Period:
                self.screenQuad.setShaderInput(param,
                                               Vec4(self.timePeriod, 0, 0, 0))

    def _cleanUpShaderInputs(self):
        for param in self.texParams.keys():
            self.screenQuad.clearShaderInput(param)

        for param in self.floatParams.keys():
            self.screenQuad.clearShaderInput(param)

        for param in self.matParams.keys():
            self.screenQuad.clearShaderInput(param)

        for param in self.predefinedParams.keys():
            self.screenQuad.clearShaderInput(param)

        self.nodesRoot.removeNode()
        self.nodesRoot = None

    def _convertTime(self, toMode):
        '''
        Converts the accumulated time, stored in self.time, to the given mode.
        It is assumed that self.time is always in the range 0..X, where X is the time period.
        '''
        if toMode == self.Time_0_1:
            #            self.log.debug('converting time %f to 0..1 range as %f' % (self.time, self.time / self.timePeriod))
            return self.time / self.timePeriod
        elif toMode == self.Time_0_2PI:
            #            self.log.debug('converting time %f to 0..2PI range as %f' % (self.time, 2.0*math.pi*self.time / self.timePeriod))
            return 2.0 * math.pi * (self.time / self.timePeriod)
        else:
            return self.time
Esempio n. 5
0
class Pipeline:
    def __init__(
        self,
        *,
        render_node=None,
        window=None,
        camera_node=None,
        taskmgr=None,
        msaa_samples=4,
        max_lights=8,
        use_normal_maps=False,
        use_emission_maps=True,
        exposure=1.0,
        enable_shadows=False,
        enable_fog=False,
        use_occlusion_maps=False,
        use_330=None,
        use_hardware_skinning=None,
    ):
        if render_node is None:
            render_node = base.render

        if window is None:
            window = base.win

        if camera_node is None:
            camera_node = base.cam

        if taskmgr is None:
            taskmgr = base.task_mgr

        self._shader_ready = False
        self.render_node = render_node
        self.window = window
        self.camera_node = camera_node
        self.max_lights = max_lights
        self.use_normal_maps = use_normal_maps
        self.use_emission_maps = use_emission_maps
        self.enable_shadows = enable_shadows
        self.enable_fog = enable_fog
        self.exposure = exposure
        self.msaa_samples = msaa_samples
        self.use_occlusion_maps = use_occlusion_maps

        self._set_use_330(use_330)
        self.enable_hardware_skinning = use_hardware_skinning if use_hardware_skinning is not None else self.use_330

        # Create a FilterManager instance
        self.manager = FilterManager(window, camera_node)

        # Do not force power-of-two textures
        p3d.Texture.set_textures_power_2(p3d.ATS_none)

        # Make sure we have AA for if/when MSAA is enabled
        self.render_node.set_antialias(p3d.AntialiasAttrib.M_auto)

        # PBR Shader
        self._recompile_pbr()

        # Tonemapping
        self._setup_tonemapping()

        # Do updates based on scene changes
        taskmgr.add(self._update, 'simplepbr update')

        self._shader_ready = True

    def _set_use_330(self, use_330):
        if use_330 is not None:
            self.use_330 = use_330
        else:
            self.use_330 = False

            cvar = p3d.ConfigVariableInt('gl-version')
            gl_version = [
                cvar.get_word(i) for i in range(cvar.get_num_words())
            ]
            if len(gl_version
                   ) >= 2 and gl_version[0] >= 3 and gl_version[1] >= 2:
                # Not exactly accurate, but setting this variable to '3 2' is common for disabling
                # the fixed-function pipeline and 3.2 support likely means 3.3 support as well.
                self.use_330 = True

    def __setattr__(self, name, value):
        if hasattr(self, name):
            prev_value = getattr(self, name)
        else:
            prev_value = None
        super().__setattr__(name, value)
        if not self._shader_ready:
            return

        pbr_vars = [
            'max_lights',
            'use_normal_maps',
            'use_emission_maps',
            'enable_shadows',
            'enable_fog',
            'use_occlusion_maps',
        ]

        def resetup_tonemap():
            # Destroy previous buffers so we can re-create
            self.manager.cleanup()

            # Create a new FilterManager instance
            self.manager = FilterManager(self.window, self.camera_node)
            self._setup_tonemapping()

        if name in pbr_vars and prev_value != value:
            self._recompile_pbr()
        elif name == 'exposure':
            self.tonemap_quad.set_shader_input('exposure', self.exposure)
        elif name == 'msaa_samples':
            self._setup_tonemapping()
        elif name == 'render_node' and prev_value != value:
            self._recompile_pbr()
        elif name in ('camera_node', 'window') and prev_value != value:
            resetup_tonemap()
        elif name == 'use_330' and prev_value != value:
            self._set_use_330(value)
            self._recompile_pbr()
            resetup_tonemap()

    def _recompile_pbr(self):
        pbr_defines = {
            'MAX_LIGHTS': self.max_lights,
        }
        if self.use_normal_maps:
            pbr_defines['USE_NORMAL_MAP'] = ''
        if self.use_emission_maps:
            pbr_defines['USE_EMISSION_MAP'] = ''
        if self.enable_shadows:
            pbr_defines['ENABLE_SHADOWS'] = ''
        if self.enable_fog:
            pbr_defines['ENABLE_FOG'] = ''
        if self.use_occlusion_maps:
            pbr_defines['USE_OCCLUSION_MAP'] = ''
        if self.use_330:
            pbr_defines['USE_330'] = ''
        if self.enable_hardware_skinning:
            pbr_defines['ENABLE_SKINNING'] = ''

        pbr_vert_str = _load_shader_str('simplepbr.vert', pbr_defines)
        pbr_frag_str = _load_shader_str('simplepbr.frag', pbr_defines)
        pbrshader = p3d.Shader.make(
            p3d.Shader.SL_GLSL,
            vertex=pbr_vert_str,
            fragment=pbr_frag_str,
        )
        attr = p3d.ShaderAttrib.make(pbrshader)
        if self.enable_hardware_skinning:
            attr = attr.set_flag(p3d.ShaderAttrib.F_hardware_skinning, True)
        self.render_node.set_attrib(attr)

    def _setup_tonemapping(self):
        if self._shader_ready:
            # Destroy previous buffers so we can re-create
            self.manager.cleanup()

            # Fix shadow buffers after FilterManager.cleanup()
            for caster in self.get_all_casters():
                sbuff_size = caster.get_shadow_buffer_size()
                caster.set_shadow_buffer_size((0, 0))
                caster.set_shadow_buffer_size(sbuff_size)

        fbprops = p3d.FrameBufferProperties()
        fbprops.float_color = True
        fbprops.set_rgba_bits(16, 16, 16, 16)
        fbprops.set_depth_bits(24)
        fbprops.set_multisamples(self.msaa_samples)
        scene_tex = p3d.Texture()
        scene_tex.set_format(p3d.Texture.F_rgba16)
        scene_tex.set_component_type(p3d.Texture.T_float)
        self.tonemap_quad = self.manager.render_scene_into(colortex=scene_tex,
                                                           fbprops=fbprops)

        defines = {}
        if self.use_330:
            defines['USE_330'] = ''

        post_vert_str = _load_shader_str('post.vert', defines)
        post_frag_str = _load_shader_str('tonemap.frag', defines)
        tonemap_shader = p3d.Shader.make(
            p3d.Shader.SL_GLSL,
            vertex=post_vert_str,
            fragment=post_frag_str,
        )
        self.tonemap_quad.set_shader(tonemap_shader)
        self.tonemap_quad.set_shader_input('tex', scene_tex)
        self.tonemap_quad.set_shader_input('exposure', self.exposure)

    def get_all_casters(self):
        return [
            i.node()
            for i in self.render_node.find_all_matches('**/+LightLensNode')
            if i.node().is_shadow_caster()
        ]

    def _update(self, task):
        # Use a simpler, faster shader for shadows
        for caster in self.get_all_casters():
            state = caster.get_initial_state()
            if not state.has_attrib(p3d.ShaderAttrib):
                defines = {}
                if self.use_330:
                    defines['USE_330'] = ''
                if self.enable_hardware_skinning:
                    defines['ENABLE_SKINNING'] = ''
                shader = p3d.Shader.make(
                    p3d.Shader.SL_GLSL,
                    vertex=_load_shader_str('shadow.vert', defines),
                    fragment=_load_shader_str('shadow.frag', defines))
                attr = p3d.ShaderAttrib.make(shader)
                if self.enable_hardware_skinning:
                    attr = attr.set_flag(p3d.ShaderAttrib.F_hardware_skinning,
                                         True)
                state = state.add_attrib(attr, 1)
                caster.set_initial_state(state)

        # Use the auto-shader for node types that simplepbr does not support
        unsupported_types = [
            'TextNode',
        ]
        nodes = [
            node for node_type in unsupported_types
            for node in self.render_node.find_all_matches(f'**/+{node_type}')
        ]
        for node in nodes:
            if not node.has_attrib(p3d.ShaderAttrib):
                node.set_shader_auto(True)

        return task.cont

    def verify_shaders(self):
        gsg = self.window.gsg

        def check_node_shader(np):
            shader = p3d.Shader(np.get_shader())
            shader.prepare_now(gsg.prepared_objects, gsg)
            assert shader.is_prepared(gsg.prepared_objects)
            assert not shader.get_error_flag()

        check_node_shader(self.render_node)
        check_node_shader(self.tonemap_quad)
Esempio n. 6
0
class Postprocess():
    def __init__(self):
        self.filter_tex={}        
        self.manager=FilterManager(base.win, base.cam)
        self.filters={}
        
        self.window_x=float(base.win.getXSize())
        self.window_y=float(base.win.getYSize())
    
    def reset(self):
        self.manager.cleanup()
        self.filter_tex={}        
        self.manager=FilterManager(base.win, base.cam)
        self.filters={}        
        self.window_x=float(base.win.getXSize())
        self.window_y=float(base.win.getYSize())
                  
    def setupFilters(self, useFxaa=True):       
        colorTex = Texture()#the scene
        colorTex.setWrapU(Texture.WMClamp)
        colorTex.setWrapV(Texture.WMClamp)
        colorTex.setFormat(Texture.F_rgb16)
        auxTex = Texture() # r=blur, g=shadow, b=?, a=?
        composeTex=Texture()#the scene(colorTex) blured where auxTex.r>0 and with shadows (blurTex2.r) added
        self.filters={}
        final_quad = self.manager.renderSceneInto(colortex=colorTex, auxtex=auxTex)
        
        
        blurTex = Texture() #1/2 size of the shadows to be blured
        blurTex.setWrapU(Texture.WMClamp)
        blurTex.setWrapV(Texture.WMClamp)
        blurTex2 = Texture()
        blurTex2.setWrapU(Texture.WMClamp)
        blurTex2.setWrapV(Texture.WMClamp)
        glareTex = Texture()
        glareTex.setWrapU(Texture.WMClamp)
        glareTex.setWrapV(Texture.WMClamp)
        flareTex = Texture()
        flareTex.setWrapU(Texture.WMClamp)
        flareTex.setWrapV(Texture.WMClamp)
        flareTex2 = Texture()
        flareTex2.setWrapU(Texture.WMClamp)
        flareTex2.setWrapV(Texture.WMClamp)
        #blurr shadows #1
        interquad0 = self.manager.renderQuadInto(colortex=blurTex, div=8)
        interquad0.setShader(Shader.load(Shader.SLGLSL, path+"shaders/blur_v.glsl", path+"shaders/blur_f.glsl"))
        interquad0.setShaderInput("input_map", auxTex)
        interquad0.setShaderInput("sharpness", 0.008)
        self.filters['shadow']=interquad0
        #blurrscene
        interquad1 = self.manager.renderQuadInto(colortex=blurTex2, div=4)
        interquad1.setShader(Shader.load(Shader.SLGLSL, path+"shaders/blur_v.glsl", path+"shaders/blur_f.glsl"))
        interquad1.setShaderInput("input_map", colorTex)        
        interquad1.setShaderInput("sharpness", 0.005)
        self.filters['blur']=interquad1
        #glare
        interquad2 = self.manager.renderQuadInto(colortex=glareTex, div=2)
        interquad2.setShader(Shader.load(Shader.SLGLSL, path+"shaders/glare_v.glsl", path+"shaders/glare_f.glsl"))
        interquad2.setShaderInput("auxTex", auxTex)
        interquad2.setShaderInput("colorTex", blurTex2)
        interquad2.setShaderInput("blurTex", blurTex)
        self.filters['glare']=interquad2
        #lense flare
        interquad3 = self.manager.renderQuadInto(colortex=flareTex, div=2)
        #interquad3.setShader(Shader.load(path+"shaders/lens_flare.sha"))
        #interquad3.setShaderInput("tex0", glareTex)
        interquad3.setShader(Shader.load(Shader.SLGLSL, path+"shaders/flare_v.glsl", path+"shaders/flare_f.glsl"))
        interquad3.setShaderInput("glareTex", glareTex)        
        self.filters['flare']=interquad3
        interquad3a = self.manager.renderQuadInto(colortex=flareTex2, div=2)
        interquad3a.setShader(Shader.load(Shader.SLGLSL, path+"shaders/blur_v.glsl", path+"shaders/blur_f.glsl"))
        interquad3a.setShaderInput("input_map", flareTex)        
        interquad3a.setShaderInput("sharpness", 0.005)        
        self.filters['flare2']=interquad1        
        if useFxaa:
            #compose the scene        
            interquad4 = self.manager.renderQuadInto(colortex=composeTex)               
            interquad4.setShader(Shader.load(Shader.SLGLSL, path+"shaders/compose_v.glsl", path+"shaders/compose_f.glsl"))
            interquad4.setShaderInput("flareTex", flareTex2)
            interquad4.setShaderInput("glareTex", glareTex)
            interquad4.setShaderInput("colorTex", colorTex)
            interquad4.setShaderInput("blurTex", blurTex)
            interquad4.setShaderInput("blurTex2", blurTex2)
            interquad4.setShaderInput("auxTex", auxTex)
            interquad4.setShaderInput("noiseTex", loader.loadTexture(path+"data/noise2.png"))
            star_tex=loader.loadTexture(path+"data/star.png")
            star_tex.setWrapU(Texture.WM_mirror_once)
            star_tex.setWrapV(Texture.WM_mirror_once)
            interquad4.setShaderInput("starTex", star_tex)
            interquad4.setShaderInput('time', 0.0)
            interquad4.setShaderInput('screen_size', Vec2(float(base.win.getXSize()),float(base.win.getYSize())))           
            #fxaa
            final_quad.setShader(Shader.load(Shader.SLGLSL, path+"shaders/fxaa_v.glsl", path+"shaders/fxaa_f.glsl"))
            final_quad.setShaderInput("tex0", composeTex)
            final_quad.setShaderInput("rt_w",float(base.win.getXSize()))
            final_quad.setShaderInput("rt_h",float(base.win.getYSize()))
            final_quad.setShaderInput("FXAA_SPAN_MAX" , float(8.0))
            final_quad.setShaderInput("FXAA_REDUCE_MUL", float(1.0/8.0))
            final_quad.setShaderInput("FXAA_SUBPIX_SHIFT", float(1.0/4.0))
            self.filters['fxaa']=final_quad
        else:
            #compose the scene  
            final_quad.setShader(Shader.load(Shader.SLGLSL, path+"shaders/compose_v.glsl", path+"shaders/compose_f.glsl"))
            final_quad.setShaderInput("flareTex", flareTex2)
            final_quad.setShaderInput("glareTex", glareTex)
            final_quad.setShaderInput("colorTex", colorTex)
            final_quad.setShaderInput("blurTex", blurTex)
            final_quad.setShaderInput("blurTex2", blurTex2)
            final_quad.setShaderInput("auxTex", auxTex)
            final_quad.setShaderInput("noiseTex", loader.loadTexture(path+"data/noise2.png"))
            star_tex=loader.loadTexture(path+"data/star.png")
            star_tex.setWrapU(Texture.WM_mirror_once)
            star_tex.setWrapV(Texture.WM_mirror_once)
            final_quad.setShaderInput("starTex", star_tex)
            final_quad.setShaderInput('time', 0.0)
            final_quad.setShaderInput('screen_size', Vec2(float(base.win.getXSize()),float(base.win.getYSize())))            
            self.filters['compose']=final_quad     
        
    def setupFxaa(self):
        colorTex = Texture()#the scene
        final_quad = self.manager.renderSceneInto(colortex=colorTex)
        final_quad.setShader(Shader.load(Shader.SLGLSL, path+"shaders/fxaa_v.glsl", path+"shaders/fxaa_f.glsl"))
        final_quad.setShaderInput("tex0", colorTex)
        final_quad.setShaderInput("rt_w",float(base.win.getXSize()))
        final_quad.setShaderInput("rt_h",float(base.win.getYSize()))
        final_quad.setShaderInput("FXAA_SPAN_MAX" , float(8.0))
        final_quad.setShaderInput("FXAA_REDUCE_MUL", float(1.0/8.0))
        final_quad.setShaderInput("FXAA_SUBPIX_SHIFT", float(1.0/4.0))
        self.filters['fxaa']=final_quad
    
    def update(self):
        x=float(base.win.getXSize())
        y=float(base.win.getYSize()) 
        if self.filters:
            if 'fxaa' in self.filters:
                self.filters['fxaa'].setShaderInput("rt_w",x)         
                self.filters['fxaa'].setShaderInput("rt_h",y)
            if 'compose' in self.filters:
                self.filters['compose'].setShaderInput("screen_size",Vec2(x,y)) 
Esempio n. 7
0
class Pipeline:
    def __init__(self,
                 *,
                 render_node=None,
                 window=None,
                 camera_node=None,
                 msaa_samples=4,
                 max_lights=8,
                 use_normal_maps=False,
                 use_emission_maps=False,
                 exposure=1.0,
                 enable_shadows=False,
                 enable_fog=False,
                 use_occlusion_maps=False):
        if render_node is None:
            render_node = base.render

        if window is None:
            window = base.win

        if camera_node is None:
            camera_node = base.cam

        self._shader_ready = False
        self.render_node = render_node
        self.window = window
        self.camera_node = camera_node
        self.max_lights = max_lights
        self.use_normal_maps = use_normal_maps
        self.use_emission_maps = use_emission_maps
        self.enable_shadows = enable_shadows
        self.enable_fog = enable_fog
        self.exposure = exposure
        self.msaa_samples = msaa_samples
        self.use_occlusion_maps = use_occlusion_maps

        # Create a FilterManager instance
        self.manager = FilterManager(window, camera_node)

        # Do not force power-of-two textures
        p3d.Texture.set_textures_power_2(p3d.ATS_none)

        # Make sure we have AA for if/when MSAA is enabled
        self.render_node.set_antialias(p3d.AntialiasAttrib.M_auto)

        # PBR Shader
        self._recompile_pbr()

        # Tonemapping
        self._setup_tonemapping()

        self._shader_ready = True

    def __setattr__(self, name, value):
        if hasattr(self, name):
            prev_value = getattr(self, name)
        else:
            prev_value = None
        super().__setattr__(name, value)
        if not self._shader_ready:
            return

        pbr_vars = [
            'max_lights',
            'use_normal_maps',
            'use_emission_maps',
            'enable_shadows',
            'enable_fog',
            'use_occlusion_maps',
        ]
        if name in pbr_vars and prev_value != value:
            self._recompile_pbr()
        elif name == 'exposure':
            self.tonemap_quad.set_shader_input('exposure', self.exposure)
        elif name == 'msaa_samples':
            self._setup_tonemapping()

    def _recompile_pbr(self):
        pbr_defines = {
            'MAX_LIGHTS': self.max_lights,
        }
        if self.use_normal_maps:
            pbr_defines['USE_NORMAL_MAP'] = ''
        if self.use_emission_maps:
            pbr_defines['USE_EMISSION_MAP'] = ''
        if self.enable_shadows:
            pbr_defines['ENABLE_SHADOWS'] = ''
        if self.enable_fog:
            pbr_defines['ENABLE_FOG'] = ''
        if self.use_occlusion_maps:
            pbr_defines['USE_OCCLUSION_MAP'] = ''

        pbr_vert_str = _load_shader_str('simplepbr.vert', pbr_defines)
        pbr_frag_str = _load_shader_str('simplepbr.frag', pbr_defines)
        pbrshader = p3d.Shader.make(
            p3d.Shader.SL_GLSL,
            vertex=pbr_vert_str,
            fragment=pbr_frag_str,
        )
        self.render_node.set_shader(pbrshader)

    def _setup_tonemapping(self):
        if self._shader_ready:
            # Destroy previous buffers so we can re-create
            self.manager.cleanup()

            # Fix shadow buffers after FilterManager.cleanup()
            for casternp in self.render_node.find_all_matches(
                    '**/+LightLensNode'):
                caster = casternp.node()
                if caster.is_shadow_caster():
                    # caster.set_shadow_caster(False)
                    # caster.set_shadow_caster(True)
                    sbuff_size = caster.get_shadow_buffer_size()
                    caster.set_shadow_buffer_size((0, 0))
                    caster.set_shadow_buffer_size(sbuff_size)

        fbprops = p3d.FrameBufferProperties()
        fbprops.float_color = True
        fbprops.set_rgba_bits(16, 16, 16, 16)
        fbprops.set_depth_bits(24)
        fbprops.set_multisamples(self.msaa_samples)
        scene_tex = p3d.Texture()
        scene_tex.set_format(p3d.Texture.F_rgba16)
        scene_tex.set_component_type(p3d.Texture.T_float)
        self.tonemap_quad = self.manager.render_scene_into(colortex=scene_tex,
                                                           fbprops=fbprops)

        post_vert_str = _load_shader_str('post.vert')
        post_frag_str = _load_shader_str('tonemap.frag')
        tonemap_shader = p3d.Shader.make(
            p3d.Shader.SL_GLSL,
            vertex=post_vert_str,
            fragment=post_frag_str,
        )
        self.tonemap_quad.set_shader(tonemap_shader)
        self.tonemap_quad.set_shader_input('tex', scene_tex)
        self.tonemap_quad.set_shader_input('exposure', self.exposure)