def _initArrays(self):

        # Max Visible Lights (limited because shaders can have max 1024 uniform
        # floats)

        # If you change this, don't forget to change it also in
        # Shader/Includes/Configuration.include!
        self.maxLights = {
            "PointLight": 8,
            # "DirectionalLight": 2
        }

        # Max shadow casting lights
        self.maxShadowLights = {
            "PointLight": 16,
            # "DirectionalLight": 1
        }

        for lightType, maxCount in self.maxShadowLights.items():
            self.maxLights[lightType + "Shadow"] = maxCount

        # Create array to store number of rendered lights this frame
        self.numRenderedLights = {}

        # Also create a PTAInt for every light type, which stores only the
        # light id
        self.renderedLightsArrays = {}
        for lightType, maxCount in self.maxLights.items():
            self.renderedLightsArrays[lightType] = PTAInt.emptyArray(maxCount)
            self.numRenderedLights[lightType] = PTAInt.emptyArray(1)

        for lightType, maxCount in self.maxShadowLights.items():
            self.renderedLightsArrays[lightType +
                                      "Shadow"] = PTAInt.emptyArray(maxCount)
            self.numRenderedLights[lightType + "Shadow"] = PTAInt.emptyArray(1)
Beispiel #2
0
    def _createInputHandles(self):
        """ Defines various inputs to be used in the shader passes. Most inputs
        use pta-arrays, so updating them is faster than using setShaderInput all the
        time. """
        self.cameraPosition = PTAVecBase3f.emptyArray(1)
        self.currentViewMat = PTALMatrix4f.emptyArray(1)
        self.currentProjMatInv = PTALMatrix4f.emptyArray(1)
        self.lastMVP = PTALMatrix4f.emptyArray(1)
        self.currentMVP = PTALMatrix4f.emptyArray(1)
        self.frameIndex = PTAInt.emptyArray(1)
        self.frameDelta = PTAFloat.emptyArray(1)

        self.renderPassManager.registerStaticVariable("lastMVP", self.lastMVP)
        self.renderPassManager.registerStaticVariable("currentMVP", self.currentMVP)
        self.renderPassManager.registerStaticVariable("frameIndex", self.frameIndex)
        self.renderPassManager.registerStaticVariable("cameraPosition", self.cameraPosition)
        self.renderPassManager.registerStaticVariable("mainCam", self.showbase.cam)
        self.renderPassManager.registerStaticVariable("mainRender", self.showbase.render)
        self.renderPassManager.registerStaticVariable("frameDelta", self.frameDelta)
        self.renderPassManager.registerStaticVariable("currentViewMat", self.currentViewMat)
        self.renderPassManager.registerStaticVariable("currentProjMatInv", self.currentProjMatInv)
        self.renderPassManager.registerStaticVariable("zeroVec2", Vec2(0))
        self.renderPassManager.registerStaticVariable("zeroVec3", Vec3(0))
        self.renderPassManager.registerStaticVariable("zeroVec4", Vec4(0))

        self.transformMat = TransformState.makeMat(Mat4.convertMat(CSYupRight, CSZupRight))
    def _init_internal_mgr(self):
        """ Creates the light storage manager and the buffer to store the light data """
        self._internal_mgr = InternalLightManager()

        # Storage for the Lights
        per_light_vec4s = 4
        self._img_light_data = Image.create_buffer(
            "LightData", self._MAX_LIGHTS * per_light_vec4s, Texture.T_float,
            Texture.F_rgba16)
        self._img_light_data.set_clear_color(0)
        self._img_light_data.clear_image()

        self._pta_max_light_index = PTAInt.empty_array(1)
        self._pta_max_light_index[0] = 0

        # Storage for the shadow sources
        per_source_vec4s = 5
        self._img_source_data = Image.create_buffer(
            "ShadowSourceData", self._MAX_SOURCES * per_source_vec4s, Texture.T_float,
            Texture.F_rgba16)
        self._img_light_data.set_clear_color(0)
        self._img_light_data.clear_image()

        # Register the buffer
        add_input = self._pipeline.stage_mgr.add_input
        add_input("AllLightsData", self._img_light_data.get_texture())
        add_input("ShadowSourceData", self._img_source_data.get_texture())
        add_input("maxLightIndex", self._pta_max_light_index)
Beispiel #4
0
    def __init__(self):
        """ Constructs a new Light, subclasses have to call this """
        DebugObject.__init__(self, "AbstractLight")
        ShaderStructElement.__init__(self)
        self.debugNode = NodePath("LightDebug")
        self.visualizationNumSteps = 32
        self.dataNeedsUpdate = False
        self.castShadows = False
        self.debugEnabled = False
        self.bounds = OmniBoundingVolume()
        self.shadowSources = []
        self.lightType = self.getLightType()
        self.position = Vec3(0)
        self.color = Vec3(1)
        self.posterIndex = -1
        self.radius = 10.0
        self.typeName = ""
        self.sourceIndexes = PTAInt.emptyArray(6)
        self.attached = False
        self.shadowResolution = 512
        self.index = -1
        self.iesProfile = -1
        self.iesProfileName = None
        self.mvp = Mat4()

        # A light can have up to 6 sources
        for i in range(6):
            self.sourceIndexes[i] = -1
    def init_internal_manager(self):
        """ Creates the light storage manager and the buffer to store the light data """
        self.internal_mgr = InternalLightManager()
        self.internal_mgr.set_shadow_update_distance(
            self.pipeline.settings["shadows.max_update_distance"])

        # Storage for the Lights
        per_light_vec4s = 4
        self.img_light_data = Image.create_buffer(
            "LightData", self.MAX_LIGHTS * per_light_vec4s, "RGBA16")
        self.img_light_data.set_clear_color(0)
        self.img_light_data.clear_image()

        self.pta_max_light_index = PTAInt.empty_array(1)
        self.pta_max_light_index[0] = 0

        # Storage for the shadow sources
        per_source_vec4s = 5
        self.img_source_data = Image.create_buffer(
            "ShadowSourceData", self.MAX_SOURCES * per_source_vec4s, "RGBA16")
        self.img_light_data.set_clear_color(0)
        self.img_light_data.clear_image()

        # Register the buffer
        inputs = self.pipeline.stage_mgr.inputs
        inputs["AllLightsData"] = self.img_light_data
        inputs["ShadowSourceData"] = self.img_source_data
        inputs["maxLightIndex"] = self.pta_max_light_index
Beispiel #6
0
    def __init__(self):
        """ Constructs a new Light, subclasses have to call this """
        DebugObject.__init__(self, "AbstractLight")
        ShaderStructElement.__init__(self)
        self.debugNode = NodePath("LightDebug")
        self.visualizationNumSteps = 32
        self.dataNeedsUpdate = False
        self.castShadows = False
        self.debugEnabled = False
        self.bounds = OmniBoundingVolume()
        self.shadowSources = []
        self.lightType = self.getLightType()
        self.position = Vec3(0)
        self.color = Vec3(1)
        self.posterIndex = -1
        self.direction = Vec3(0)
        self.radius = 10.0
        self.typeName = ""
        self.sourceIndexes = PTAInt.emptyArray(6)
        self.attached = False
        self.shadowResolution = 512
        self.index = -1
        self.iesProfile = -1
        self.iesProfileName = None
        self.mvp = Mat4()

        # A light can have up to 6 sources
        for i in range(6):
            self.sourceIndexes[i] = -1
    def init_internal_manager(self):
        """ Creates the light storage manager and the buffer to store the light data """
        self.internal_mgr = InternalLightManager()
        self.internal_mgr.set_shadow_update_distance(
            self.pipeline.settings["shadows.max_update_distance"])

        # Storage for the Lights
        per_light_vec4s = 4
        self.img_light_data = Image.create_buffer(
            "LightData", self.MAX_LIGHTS * per_light_vec4s, "RGBA16")
        self.img_light_data.clear_image()

        self.pta_max_light_index = PTAInt.empty_array(1)
        self.pta_max_light_index[0] = 0

        # Storage for the shadow sources
        per_source_vec4s = 5

        # IMPORTANT: RGBA32 is really required here. Otherwise artifacts and bad
        # shadow filtering occur due to precision issues
        self.img_source_data = Image.create_buffer(
            "ShadowSourceData", self.MAX_SOURCES * per_source_vec4s, "RGBA32")
        self.img_light_data.clear_image()

        # Register the buffer
        inputs = self.pipeline.stage_mgr.inputs
        inputs["AllLightsData"] = self.img_light_data
        inputs["ShadowSourceData"] = self.img_source_data
        inputs["maxLightIndex"] = self.pta_max_light_index
Beispiel #8
0
    def _create_components(self):
        """ Internal method to init the widgets components """

        # Create the buffer which stores the last FPS values
        self._storage_buffer = Image.create_buffer("FPSValues", 250, "R16")
        self._storage_buffer.set_clear_color(Vec4(0))
        self._storage_buffer.clear_image()

        self._store_index = PTAInt.empty_array(1)
        self._store_index[0] = 0

        self._current_ftime = PTAFloat.empty_array(1)
        self._current_ftime[0] = 16.0

        self._chart_ms_max = PTAFloat.empty_array(1)
        self._chart_ms_max[0] = 40

        # Create the texture where the gui component is rendered inside
        self._display_tex = Image.create_2d("FPSChartRender", 250, 120,
                                            "RGBA8")
        self._display_tex.set_clear_color(Vec4(0))
        self._display_tex.clear_image()
        self._display_img = Sprite(image=self._display_tex,
                                   parent=self._node,
                                   w=250,
                                   h=120,
                                   x=10,
                                   y=10)

        # Defer the further loading
        Globals.base.taskMgr.doMethodLater(0.3, self._late_init,
                                           "FPSChartInit")
Beispiel #9
0
    def init_internal_manager(self):
        """ Creates the light storage manager and the buffer to store the light data """
        self.internal_mgr = InternalLightManager()
        self.internal_mgr.set_shadow_update_distance(
            self.pipeline.settings["shadows.max_update_distance"])

        # Storage for the Lights
        per_light_vec4s = 4
        self.img_light_data = Image.create_buffer(
            "LightData", self.MAX_LIGHTS * per_light_vec4s, "RGBA16")
        self.img_light_data.set_clear_color(0)
        self.img_light_data.clear_image()

        self.pta_max_light_index = PTAInt.empty_array(1)
        self.pta_max_light_index[0] = 0

        # Storage for the shadow sources
        per_source_vec4s = 5

        # IMPORTANT: RGBA32 is really required here. Otherwise artifacts and bad
        # shadow filtering occur due to precision issues
        self.img_source_data = Image.create_buffer(
            "ShadowSourceData", self.MAX_SOURCES * per_source_vec4s, "RGBA32")
        self.img_light_data.set_clear_color(0)
        self.img_light_data.clear_image()

        # Register the buffer
        inputs = self.pipeline.stage_mgr.inputs
        inputs["AllLightsData"] = self.img_light_data
        inputs["ShadowSourceData"] = self.img_source_data
        inputs["maxLightIndex"] = self.pta_max_light_index
Beispiel #10
0
    def _create_components(self):
        """ Internal method to init the widgets components """

        # Create the buffer which stores the last FPS values
        self._storage_buffer = Image.create_buffer("FPSValues", 250, "R16")
        self._storage_buffer.set_clear_color(Vec4(0))
        self._storage_buffer.clear_image()

        self._store_index = PTAInt.empty_array(1)
        self._store_index[0] = 0

        self._current_ftime = PTAFloat.empty_array(1)
        self._current_ftime[0] = 16.0

        self._chart_ms_max = PTAFloat.empty_array(1)
        self._chart_ms_max[0] = 40

        # Create the texture where the gui component is rendered inside
        self._display_tex = Image.create_2d("FPSChartRender", 250, 120, "RGBA8")
        self._display_tex.set_clear_color(Vec4(0))
        self._display_tex.clear_image()
        self._display_img = Sprite(
            image=self._display_tex, parent=self._node, w=250, h=120, x=10, y=10)

        # Defer the further loading
        Globals.base.taskMgr.doMethodLater(0.3, self._late_init, "FPSChartInit")
Beispiel #11
0
 def __init__(self, pipeline):
     RenderStage.__init__(self, pipeline)
     self.resolution = 128
     self.diffuse_resolution = 4
     self.regions = []
     self.cameras = []
     self.rig_node = Globals.render.attach_new_node("EnvmapCamRig")
     self.pta_index = PTAInt.empty_array(1)
     self.storage_tex = None
     self.storage_tex_diffuse = None
 def __init__(self, pipeline):
     RenderStage.__init__(self, pipeline)
     self.resolution = 128
     self.diffuse_resolution = 4
     self.regions = []
     self.cameras = []
     self.rig_node = Globals.render.attach_new_node("EnvmapCamRig")
     self.pta_index = PTAInt.empty_array(1)
     self.storage_tex = None
     self.storage_tex_diffuse = None
 def __init__(self, pipeline):
     DebugObject.__init__(self, "GPUCommandQueue")
     self._pipeline = pipeline
     self._commands_per_frame = 512
     self._command_list = GPUCommandList()
     self._pta_num_commands = PTAInt.empty_array(1)
     self._create_data_storage()
     self._create_command_target()
     self._commands = []
     self._register_defines()
 def __init__(self, pipeline):
     RPObject.__init__(self)
     self._pipeline = pipeline
     self._commands_per_frame = 1024
     self._command_list = GPUCommandList()
     self._pta_num_commands = PTAInt.empty_array(1)
     self._create_data_storage()
     self._create_command_target()
     self._commands = []
     self._register_defines()
    def _setup_inputs(self):
        """ Sets all required inputs """
        self.pta_probes = PTAInt.empty_array(1)

        # Construct the UBO which stores all environment probe data
        self.data_ubo = SimpleInputBlock("EnvProbes")
        self.data_ubo.add_input("num_probes", self.pta_probes)
        self.data_ubo.add_input("cubemaps", self.probe_mgr.cubemap_storage)
        self.data_ubo.add_input("diffuse_cubemaps", self.probe_mgr.diffuse_storage)
        self.data_ubo.add_input("dataset", self.probe_mgr.dataset_storage)
        self._pipeline.stage_mgr.input_blocks.append(self.data_ubo)

        # Use the UBO in light culling
        CullLightsStage.required_inputs.append("EnvProbes")
Beispiel #16
0
    def _initArrays(self):
        """ Inits the light arrays which are passed to the shaders """

        # If you change this, don't forget to change it also in
        # Shader/Includes/Configuration.include!
        self.maxLights = {
            "PointLight": 16,
            "DirectionalLight": 1
        }

        # Max shadow casting lights
        self.maxShadowLights = {
            "PointLight": 16,
            "DirectionalLight": 1,
            "GIHelperLight": 10
        }

        self.maxTotalLights = 8

        for lightType, maxCount in self.maxShadowLights.items():
            self.maxLights[lightType + "Shadow"] = maxCount

        # Create array to store number of rendered lights this frame
        self.numRenderedLights = {}

        # Also create a PTAInt for every light type, which stores only the
        # light id, the lighting shader will then lookup the light in the
        # global lights array.
        self.renderedLightsArrays = {}
        for lightType, maxCount in self.maxLights.items():
            self.renderedLightsArrays[lightType] = PTAInt.emptyArray(maxCount)
            self.numRenderedLights[lightType] = PTAInt.emptyArray(1)

        for lightType, maxCount in self.maxShadowLights.items():
            self.renderedLightsArrays[
                lightType + "Shadow"] = PTAInt.emptyArray(maxCount)
            self.numRenderedLights[lightType + "Shadow"] = PTAInt.emptyArray(1)
Beispiel #17
0
    def _initArrays(self):
        """ Inits the light arrays which are passed to the shaders """

        # If you change this, don't forget to change it also in
        # Shader/Includes/Configuration.include!
        self.maxLights = {
            "PointLight": 16,
            "DirectionalLight": 1
        }

        # Max shadow casting lights
        self.maxShadowLights = {
            "PointLight": 16,
            "DirectionalLight": 1
        }

        self.maxTotalLights = 8

        for lightType, maxCount in self.maxShadowLights.items():
            self.maxLights[lightType + "Shadow"] = maxCount

        # Create array to store number of rendered lights this frame
        self.numRenderedLights = {}

        # Also create a PTAInt for every light type, which stores only the
        # light id, the lighting shader will then lookup the light in the
        # global lights array.
        self.renderedLightsArrays = {}
        for lightType, maxCount in self.maxLights.items():
            self.renderedLightsArrays[lightType] = PTAInt.emptyArray(maxCount)
            self.numRenderedLights[lightType] = PTAInt.emptyArray(1)

        for lightType, maxCount in self.maxShadowLights.items():
            self.renderedLightsArrays[
                lightType + "Shadow"] = PTAInt.emptyArray(maxCount)
            self.numRenderedLights[lightType + "Shadow"] = PTAInt.emptyArray(1)
Beispiel #18
0
    def __init__(self):
        DebugObject.__init__(self, "AbstractLight")
        self.debugNode = NodePath("LightDebug")
        self.visualizationNumSteps = 32
        self.dataNeedsUpdate = False
        self.castShadows = False
        self.debugEnabled = False
        self.bounds = OmniBoundingVolume()

        self.shadowSources = []
        self.lightType = self._getLightType()
        self.position = Vec3(0)
        self.color = Vec3(0)
        self.posterIndex = -1
        self.direction = Vec3(0)
        self.radius = 0.1
        self.typeName = ""
        self.sourceIndexes = PTAInt.emptyArray(6)
        for i in xrange(6):
            self.sourceIndexes[i] = -1
Beispiel #19
0
    def __init__(self, pipeline):
        """ Creates a new LightManager. It expects a RenderPipeline as parameter. """
        DebugObject.__init__(self, "LightManager")

        self._initArrays()

        self.pipeline = pipeline
        self.settings = pipeline.getSettings()

        # Create arrays to store lights & shadow sources
        self.lights = []
        self.shadowSources = []
        self.queuedShadowUpdates = []
        self.allLightsArray = ShaderStructArray(Light, self.maxTotalLights)
        self.updateCallbacks = []

        self.cullBounds = None
        self.shadowScene = Globals.render

        # Create atlas
        self.shadowAtlas = ShadowAtlas()
        self.shadowAtlas.setSize(self.settings.shadowAtlasSize)
        self.shadowAtlas.create()

        self.maxShadowMaps = 24
        self.maxShadowUpdatesPerFrame = self.settings.maxShadowUpdatesPerFrame
        self.numShadowUpdatesPTA = PTAInt.emptyArray(1)

        self.updateShadowsArray = ShaderStructArray(
            ShadowSource, self.maxShadowUpdatesPerFrame)
        self.allShadowsArray = ShaderStructArray(
            ShadowSource, self.maxShadowMaps)


        # Create shadow compute buffer
        self._createShadowComputationBuffer()

        # Create the initial shadow state
        self.shadowComputeCamera.setTagStateKey("ShadowPassShader")
        self._createTagStates()
        self.shadowScene.setTag("ShadowPassShader", "Default")

        # Create debug overlay
        self._createDebugTexts()

        # Disable buffer on start
        self.shadowComputeTarget.setActive(False)

        # Bind arrays
        self.updateShadowsArray.bindTo(self.shadowScene, "updateSources")
        self.updateShadowsArray.bindTo(
            self.shadowComputeTarget, "updateSources")

        # Set initial inputs
        for target in [self.shadowComputeTarget, self.shadowScene]:
            target.setShaderInput("numUpdates", self.numShadowUpdatesPTA)

        self.lightingComputator = None
        self.lightCuller = None
        self.skip = 0
        self.skipRate = 0
 def __init__(self):
     RenderPass.__init__(self)
     self.currentIndex = PTAInt.emptyArray(1)
     self.currentIndex[0] = 0
Beispiel #21
0
 def __init__(self):
     """ Creates this Technique """
     AntialiasingTechnique.__init__(self, "SMAA")
     self.currentIndex = PTAInt.emptyArray(1)
     self.currentIndex[0] = 0
    def create(self):
        """ Creates this pipeline """

        self.debug("Setting up render pipeline")

        if self.settings is None:
            self.error("You have to call loadSettings first!")
            return

        self.debug("Analyzing system ..")
        SystemAnalyzer.analyze()


        self.debug("Checking required Panda3D version ..")
        SystemAnalyzer.checkPandaVersionOutOfDate(7,8,2014)


        # Mount everything first
        self.mountManager.mount()

        # Store globals, as cython can't handle them
        self.debug("Setting up globals")
        Globals.load(self.showbase)
        Globals.font = loader.loadFont("Data/Font/SourceSansPro-Semibold.otf")
        Globals.font.setPixelsPerUnit(25)

        # Setting up shader loading
        BetterShader._DumpShaders = self.settings.dumpGeneratedShaders

        # We use PTA's for shader inputs, because that's faster than
        # using setShaderInput
        self.temporalProjXOffs = PTAInt.emptyArray(1)
        self.cameraPosition = PTAVecBase3f.emptyArray(1)
        self.motionBlurFactor = PTAFloat.emptyArray(1)
        self.lastMVP = PTALMatrix4f.emptyArray(1)
        self.currentMVP = PTALMatrix4f.emptyArray(1)
        self.currentShiftIndex = PTAInt.emptyArray(1)

        # Initialize variables
        self.camera = self.showbase.cam
        self.size = self._getSize()
        self.cullBounds = None

        # For the temporal reprojection it is important that the window width
        # is a multiple of 2
        if self.settings.enableTemporalReprojection and self.size.x % 2 == 1:
            self.error(
                "The window has to have a width which is a multiple of 2 "
                "(Current: ", self.showbase.win.getXSize(), ")")
            self.error(
                "I'll correct that for you, but next time pass the correct "
                "window size!")

            wp = WindowProperties()
            wp.setSize(
                self.showbase.win.getXSize() + 1, self.showbase.win.getYSize())
            self.showbase.win.requestProperties(wp)
            self.showbase.graphicsEngine.openWindows()

            # Get new size
            self.size = self._getSize()

        # Debug variables to disable specific features
        self.haveLightingPass = True

        # haveCombiner can only be true when haveLightingPass is enabled
        self.haveCombiner = True
        self.haveMRT = True

        # Not as good as I want it, so disabled. I'll work on it.
        self.blurEnabled = False

        self.debug("Window size is", self.size.x, "x", self.size.y)

        self.showbase.camLens.setNearFar(0.1, 50000)
        self.showbase.camLens.setFov(115)

        self.showbase.win.setClearColor(Vec4(1.0, 0.0, 1.0, 1.0))

        # Create GI handleer
        if self.settings.enableGlobalIllumination:
            self._setupGlobalIllumination()

        # Create occlusion handler
        self._setupOcclusion()

        if self.settings.displayOnscreenDebugger:
            self.guiManager = PipelineGuiManager(self)
            self.guiManager.setup()

        # Generate auto-configuration for shaders
        self._generateShaderConfiguration()

        # Create light manager, which handles lighting + shadows
        if self.haveLightingPass:
            self.lightManager = LightManager(self)

        self.patchSize = LVecBase2i(
            self.settings.computePatchSizeX,
            self.settings.computePatchSizeY)

        # Create separate scene graphs. The deferred graph is render
        self.forwardScene = NodePath("Forward-Rendering")
        self.transparencyScene = NodePath("Transparency-Rendering")
        self.transparencyScene.setBin("transparent", 30)

        # We need no transparency (we store other information in the alpha
        # channel)
        self.showbase.render.setAttrib(
            TransparencyAttrib.make(TransparencyAttrib.MNone), 100)

        # Now create deferred render buffers
        self._makeDeferredTargets()

        # Create the target which constructs the view-space normals and
        # position from world-space position
        if self.occlusion.requiresViewSpacePosNrm():
            self._createNormalPrecomputeBuffer()

        # Setup the buffers for lighting
        self._createLightingPipeline()

        # Setup combiner for temporal reprojetion
        if self.haveCombiner and self.settings.enableTemporalReprojection:
            self._createCombiner()

        if self.occlusion.requiresBlurring():
            self._createOcclusionBlurBuffer()

        self._setupAntialiasing()

        if self.blurEnabled:
            self._createDofStorage()
            self._createBlurBuffer()

        # Not sure why it has to be 0.25. But that leads to the best result
        aspect = float(self.size.y) / self.size.x
        self.onePixelShift = Vec2(
            0.125 / self.size.x, 0.125 / self.size.y / aspect) * self.settings.jitterAmount

        # Annoying that Vec2 has no multliply-operator for non-floats
        multiplyVec2 = lambda a, b: Vec2(a.x*b.x, a.y*b.y)

        if self.antialias.requiresJittering():
            self.pixelShifts = [
                multiplyVec2(self.onePixelShift, Vec2(-0.25,  0.25)),
                multiplyVec2(self.onePixelShift, Vec2(0.25, -0.25))
            ]
        else:
            self.pixelShifts = [Vec2(0), Vec2(0)]
        self.currentPixelShift = PTAVecBase2f.emptyArray(1)
        self.lastPixelShift = PTAVecBase2f.emptyArray(1)

        self._setupFinalPass()
        self._setShaderInputs()

        # add update task
        self._attachUpdateTask()
Beispiel #23
0
    def create(self):
        """ Creates this pipeline """

        self.debug("Setting up render pipeline")

        if self.settings is None:
            self.error("You have to call loadSettings first!")
            return

        self.debug("Analyzing system ..")
        SystemAnalyzer.analyze()

        self.debug("Checking required Panda3D version ..")
        SystemAnalyzer.checkPandaVersionOutOfDate(01, 12, 2014)

        # Mount everything first
        self.mountManager.mount()

        # Store globals, as cython can't handle them
        self.debug("Setting up globals")
        Globals.load(self.showbase)
        Globals.font = loader.loadFont("Data/Font/SourceSansPro-Semibold.otf")
        Globals.font.setPixelsPerUnit(25)

        # Setting up shader loading
        BetterShader._DumpShaders = self.settings.dumpGeneratedShaders

        # We use PTA's for shader inputs, because that's faster than
        # using setShaderInput
        self.temporalProjXOffs = PTAInt.emptyArray(1)
        self.cameraPosition = PTAVecBase3f.emptyArray(1)
        self.motionBlurFactor = PTAFloat.emptyArray(1)
        self.lastMVP = PTALMatrix4f.emptyArray(1)
        self.currentMVP = PTALMatrix4f.emptyArray(1)
        self.currentShiftIndex = PTAInt.emptyArray(1)

        # Initialize variables
        self.camera = self.showbase.cam
        self.size = self._getSize()
        self.cullBounds = None

        # For the temporal reprojection it is important that the window width
        # is a multiple of 2
        if self.settings.enableTemporalReprojection and self.size.x % 2 == 1:
            self.error(
                "The window has to have a width which is a multiple of 2 "
                "(Current: ", self.showbase.win.getXSize(), ")")
            self.error(
                "I'll correct that for you, but next time pass the correct "
                "window size!")

            wp = WindowProperties()
            wp.setSize(self.showbase.win.getXSize() + 1,
                       self.showbase.win.getYSize())
            self.showbase.win.requestProperties(wp)
            self.showbase.graphicsEngine.openWindows()

            # Get new size
            self.size = self._getSize()

        # Debug variables to disable specific features
        self.haveLightingPass = True

        # haveCombiner can only be true when haveLightingPass is enabled
        self.haveCombiner = True
        self.haveMRT = True

        # Not as good as I want it, so disabled. I'll work on it.
        self.blurEnabled = False

        self.debug("Window size is", self.size.x, "x", self.size.y)

        self.showbase.camLens.setNearFar(0.1, 50000)
        self.showbase.camLens.setFov(90)

        self.showbase.win.setClearColor(Vec4(1.0, 0.0, 1.0, 1.0))

        # Create GI handler
        if self.settings.enableGlobalIllumination:
            self._setupGlobalIllumination()

        # Create occlusion handler
        self._setupOcclusion()

        if self.settings.displayOnscreenDebugger:
            self.guiManager = PipelineGuiManager(self)
            self.guiManager.setup()

        # Generate auto-configuration for shaders
        self._generateShaderConfiguration()

        # Create light manager, which handles lighting + shadows
        if self.haveLightingPass:
            self.lightManager = LightManager(self)

        self.patchSize = LVecBase2i(self.settings.computePatchSizeX,
                                    self.settings.computePatchSizeY)

        # Create separate scene graphs. The deferred graph is render
        self.forwardScene = NodePath("Forward-Rendering")
        self.transparencyScene = NodePath("Transparency-Rendering")
        self.transparencyScene.setBin("transparent", 30)

        # We need no transparency (we store other information in the alpha
        # channel)
        self.showbase.render.setAttrib(
            TransparencyAttrib.make(TransparencyAttrib.MNone), 100)

        # Now create deferred render buffers
        self._makeDeferredTargets()

        # Create the target which constructs the view-space normals and
        # position from world-space position
        if self.occlusion.requiresViewSpacePosNrm():
            self._createNormalPrecomputeBuffer()

        if self.settings.enableGlobalIllumination:
            self._creatGIPrecomputeBuffer()

        # Setup the buffers for lighting
        self._createLightingPipeline()

        # Setup combiner for temporal reprojetion
        if self.haveCombiner and self.settings.enableTemporalReprojection:
            self._createCombiner()

        if self.occlusion.requiresBlurring():
            self._createOcclusionBlurBuffer()

        self._setupAntialiasing()

        if self.blurEnabled:
            self._createDofStorage()
            self._createBlurBuffer()

        # Not sure why it has to be 0.25. But that leads to the best result
        aspect = float(self.size.y) / self.size.x
        self.onePixelShift = Vec2(0.125 / self.size.x, 0.125 / self.size.y /
                                  aspect) * self.settings.jitterAmount

        # Annoying that Vec2 has no multliply-operator for non-floats
        multiplyVec2 = lambda a, b: Vec2(a.x * b.x, a.y * b.y)

        if self.antialias.requiresJittering():
            self.pixelShifts = [
                multiplyVec2(self.onePixelShift, Vec2(-0.25, 0.25)),
                multiplyVec2(self.onePixelShift, Vec2(0.25, -0.25))
            ]
        else:
            self.pixelShifts = [Vec2(0), Vec2(0)]
        self.currentPixelShift = PTAVecBase2f.emptyArray(1)
        self.lastPixelShift = PTAVecBase2f.emptyArray(1)

        self._setupFinalPass()
        self._setShaderInputs()

        # Give the gui a hint when the pipeline is done loading
        if self.settings.displayOnscreenDebugger:
            self.guiManager.onPipelineLoaded()

        # add update task
        self._attachUpdateTask()
Beispiel #24
0
 def __init__(self, pipeline):
     RenderStage.__init__(self, pipeline)
     self.area_tex = None
     self.search_tex = None
     self.use_reprojection = True
     self._jitter_index = PTAInt.empty_array(1)
 def __init__(self):
     RenderPass.__init__(self)
     self.currentIndex = PTAInt.emptyArray(1)
     self.currentIndex[0] = 0
    def create(self):
        """ Creates this pipeline """

        self.debug("Setting up render pipeline")

        if self.settings is None:
            self.error("You have to call loadSettings first!")
            return

        # Mount everything first
        self.mountManager.mount()

        # Store globals, as cython can't handle them
        self.debug("Setting up globals")
        Globals.load(self.showbase)

        # Setting up shader loading
        BetterShader._DumpShaders = self.settings.dumpGeneratedShaders

        # We use PTA's for shader inputs, because that's faster than
        # using setShaderInput
        self.temporalProjXOffs = PTAInt.emptyArray(1)
        self.cameraPosition = PTAVecBase3f.emptyArray(1)
        self.motionBlurFactor = PTAFloat.emptyArray(1)
        self.lastMVP = PTALMatrix4f.emptyArray(1)
        self.currentMVP = PTALMatrix4f.emptyArray(1)

        # Create onscreen gui

        # For the temporal reprojection it is important that the window width
        # is a multiple of 2
        if self.showbase.win.getXSize() % 2 == 1:
            self.error(
                "The window has to have a width which is a multiple of 2 "
                "(Current: ", self.showbase.win.getXSize(), ")")
            self.error(
                "I'll correct that for you, but next time pass the correct "
                "window size!")

            wp = WindowProperties()
            wp.setSize(
                self.showbase.win.getXSize() + 1, self.showbase.win.getYSize())
            self.showbase.win.requestProperties(wp)
            self.showbase.graphicsEngine.openWindows()



        self.camera = self.showbase.cam
        self.size = self._getSize()
        self.cullBounds = None

        # Debug variables to disable specific features
        self.haveLightingPass = True

        # haveCombiner can only be true when haveLightingPass is enabled
        self.haveCombiner = True
        self.haveMRT = True

        # Not as good as I want it, so disabled. I'll work on it.
        self.blurEnabled = False

        self.debug("Window size is", self.size.x, "x", self.size.y)

        self.showbase.camLens.setNearFar(0.1, 50000)
        self.showbase.camLens.setFov(90)


        self.showbase.win.setClearColor(Vec4(1.0,0.0,1.0,1.0))

        # Create occlusion handler
        self._setupOcclusion()

        if self.settings.displayOnscreenDebugger:
            self.guiManager = PipelineGuiManager(self)
            self.guiManager.setup()


        # Generate auto-configuration for shaders
        self._generateShaderConfiguration()


        # Create light manager, which handles lighting + shadows
        if self.haveLightingPass:
            self.lightManager = LightManager(self)

        self.patchSize = LVecBase2i(
            self.settings.computePatchSizeX,
            self.settings.computePatchSizeY)

        # Create separate scene graphs. The deferred graph is render
        self.forwardScene = NodePath("Forward-Rendering")
        self.transparencyScene = NodePath("Transparency-Rendering")

        # We need no transparency (we store other information in the alpha
        # channel)
        self.showbase.render.setAttrib(
            TransparencyAttrib.make(TransparencyAttrib.MNone), 100)

        # Now create deferred render buffers
        self._makeDeferredTargets()

        # Create the target which constructs the view-space normals and
        # position from world-space position
        if self.occlusion.requiresViewSpacePosNrm():
            self._createNormalPrecomputeBuffer()

        # Setup the buffers for lighting
        self._createLightingPipeline()

        # Setup combiner for temporal reprojetion
        if self.haveCombiner:
            self._createCombiner()

        if self.occlusion.requiresBlurring():
            self._createOcclusionBlurBuffer()

        self._setupAntialiasing()

        if self.blurEnabled:
            self._createDofStorage()
            self._createBlurBuffer()

        self._setupFinalPass()
        self._setShaderInputs()

        # add update task
        self._attachUpdateTask()
    def __init__(self):
        DebugObject.__init__(self, "LightManager")

        self._initArrays()

        # create arrays to store lights & shadow sources
        self.lights = []
        self.shadowSources = []
        self.allLightsArray = ShaderStructArray(Light, 30)

        self.cullBounds = None
        self.shadowScene = render

        ## SHADOW ATLAS ##
        # todo: move to separate class

        # When you change this, change also SHADOW_MAP_ATLAS_SIZE in configuration.include,
        # and reduce the default shadow map resolution of point lights
        self.shadowAtlasSize = 512
        self.maxShadowMaps = 24

        # When you change it , change also SHAODOW_GEOMETRY_MAX_VERTICES and
        # SHADOW_MAX_UPDATES_PER_FRAME in configuration.include!
        self.maxShadowUpdatesPerFrame = 2
        self.tileSize = 128
        self.tileCount = self.shadowAtlasSize / self.tileSize
        self.tiles = []

        self.updateShadowsArray = ShaderStructArray(
            ShadowSource, self.maxShadowUpdatesPerFrame)
        self.allShadowsArray = ShaderStructArray(ShadowSource,
                                                 self.maxShadowMaps)

        # self.shadowAtlasTex = Texture("ShadowAtlas")
        # self.shadowAtlasTex.setup2dTexture(
        #     self.shadowAtlasSize, self.shadowAtlasSize, Texture.TFloat, Texture.FRg16)
        # self.shadowAtlasTex.setMinfilter(Texture.FTLinear)
        # self.shadowAtlasTex.setMagfilter(Texture.FTLinear)

        self.debug("Init shadow atlas with tileSize =", self.tileSize,
                   ", tileCount =", self.tileCount)

        for i in xrange(self.tileCount):
            self.tiles.append([None for j in xrange(self.tileCount)])

        # create shadow compute buffer
        self.shadowComputeCamera = Camera("ShadowComputeCamera")
        self.shadowComputeCameraNode = self.shadowScene.attachNewNode(
            self.shadowComputeCamera)
        self.shadowComputeCamera.getLens().setFov(90, 90)
        self.shadowComputeCamera.getLens().setNearFar(10.0, 100000.0)

        self.shadowComputeCameraNode.setPos(0, 0, 150)
        self.shadowComputeCameraNode.lookAt(0, 0, 0)

        self.shadowComputeTarget = RenderTarget("ShadowCompute")
        self.shadowComputeTarget.setSize(self.shadowAtlasSize,
                                         self.shadowAtlasSize)
        # self.shadowComputeTarget.setLayers(self.maxShadowUpdatesPerFrame)
        self.shadowComputeTarget.addRenderTexture(RenderTargetType.Depth)
        self.shadowComputeTarget.setDepthBits(32)
        self.shadowComputeTarget.setSource(self.shadowComputeCameraNode,
                                           base.win)
        self.shadowComputeTarget.prepareSceneRender()

        self.shadowComputeTarget.getInternalRegion().setSort(3)
        self.shadowComputeTarget.getRegion().setSort(3)

        self.shadowComputeTarget.getInternalRegion().setNumRegions(
            self.maxShadowUpdatesPerFrame + 1)
        self.shadowComputeTarget.getInternalRegion().setDimensions(
            0, (0, 1, 0, 1))
        self.shadowComputeTarget.setClearDepth(False)

        self.depthClearer = []

        for i in xrange(self.maxShadowUpdatesPerFrame):
            buff = self.shadowComputeTarget.getInternalBuffer()
            dr = buff.makeDisplayRegion()
            dr.setSort(2)
            dr.setClearDepthActive(True)
            dr.setClearDepth(1.0)
            dr.setClearColorActive(False)
            dr.setDimensions(0, 0, 0, 0)
            self.depthClearer.append(dr)

        self.queuedShadowUpdates = []

        # Assign copy shader
        self._setCopyShader()
        # self.shadowComputeTarget.setShaderInput("atlas", self.shadowComputeTarget.getColorTexture())
        # self.shadowComputeTarget.setShaderInput(
        #     "renderResult", self.shadowComputeTarget.getDepthTexture())

        # self.shadowComputeTarget.setActive(False)

        # Create shadow caster shader
        self.shadowCasterShader = BetterShader.load(
            "Shader/DefaultShadowCaster.vertex",
            "Shader/DefaultShadowCaster.fragment",
            "Shader/DefaultShadowCaster.geometry")

        self.shadowComputeCamera.setTagStateKey("ShadowPass")
        initialState = NodePath("ShadowCasterState")
        initialState.setShader(self.shadowCasterShader, 30)
        self.shadowComputeCamera.setInitialState(
            RenderState.make(ColorWriteAttrib.make(ColorWriteAttrib.C_off),
                             DepthWriteAttrib.make(DepthWriteAttrib.M_on),
                             100))

        self.shadowComputeCamera.setTagState("True", initialState.getState())
        self.shadowScene.setTag("ShadowPass", "True")

        self._createDebugTexts()

        self.updateShadowsArray.bindTo(self.shadowScene, "updateSources")
        self.updateShadowsArray.bindTo(self.shadowComputeTarget,
                                       "updateSources")

        self.numShadowUpdatesPTA = PTAInt.emptyArray(1)

        # Set initial inputs
        for target in [self.shadowComputeTarget, self.shadowScene]:
            target.setShaderInput("numUpdates", self.numShadowUpdatesPTA)

        self.lightingComputator = None
        self.lightCuller = None
Beispiel #28
0
    def __init__(self, pipeline):
        """ Creates a new LightManager. It expects a RenderPipeline as parameter. """
        DebugObject.__init__(self, "LightManager")

        self.lightSlots = [None] * LightLimits.maxTotalLights
        self.shadowSourceSlots = [None] * LightLimits.maxShadowMaps

        self.queuedShadowUpdates = []
        self.renderedLights = {}

        self.pipeline = pipeline

        # Create arrays to store lights & shadow sources
        self.allLightsArray = ShaderStructArray(Light,
                                                LightLimits.maxTotalLights)
        self.updateCallbacks = []

        self.cullBounds = None
        self.numTiles = None
        self.lightingComputator = None
        self.shadowScene = Globals.render

        # Create atlas
        self.shadowAtlas = ShadowAtlas()
        self.shadowAtlas.setSize(self.pipeline.settings.shadowAtlasSize)
        self.shadowAtlas.create()

        self.maxShadowUpdatesPerFrame = self.pipeline.settings.maxShadowUpdatesPerFrame
        self.numShadowUpdatesPTA = PTAInt.emptyArray(1)

        self.updateShadowsArray = ShaderStructArray(
            ShadowSource, self.maxShadowUpdatesPerFrame)
        self.allShadowsArray = ShaderStructArray(ShadowSource,
                                                 LightLimits.maxShadowMaps)

        self._initLightCulling()

        # Create shadow compute buffer
        self._createShadowPass()
        self._createUnshadowedLightsPass()
        self._createShadowedLightsPass()
        self._createApplyLightsPass()
        self._createExposurePass()

        if self.pipeline.settings.enableScattering:
            self._createScatteringPass()

        # Create the initial shadow state
        self.shadowScene.setTag("ShadowPassShader", "Default")

        # Register variables & arrays
        self.pipeline.getRenderPassManager().registerDynamicVariable(
            "shadowUpdateSources", self._bindUpdateSources)
        self.pipeline.getRenderPassManager().registerDynamicVariable(
            "allLights", self._bindAllLights)
        self.pipeline.getRenderPassManager().registerDynamicVariable(
            "allShadowSources", self._bindAllSources)

        self.pipeline.getRenderPassManager().registerStaticVariable(
            "numShadowUpdates", self.numShadowUpdatesPTA)

        self._loadIESProfiles()
        self._addShaderDefines()
        self._createDebugTexts()
Beispiel #29
0
    def __init__(self, pipeline):
        """ Creates a new LightManager. It expects a RenderPipeline as parameter. """
        DebugObject.__init__(self, "LightManager")

        self._initArrays()

        self.pipeline = pipeline
        self.settings = pipeline.getSettings()

        # Create arrays to store lights & shadow sources
        self.lights = []
        self.shadowSources = []
        self.queuedShadowUpdates = []
        self.allLightsArray = ShaderStructArray(Light, self.maxTotalLights)
        self.updateCallbacks = []

        self.cullBounds = None
        self.shadowScene = Globals.render

        # Create atlas
        self.shadowAtlas = ShadowAtlas()
        self.shadowAtlas.setSize(self.settings.shadowAtlasSize)
        self.shadowAtlas.create()

        self.maxShadowMaps = 24
        self.maxShadowUpdatesPerFrame = self.settings.maxShadowUpdatesPerFrame
        self.numShadowUpdatesPTA = PTAInt.emptyArray(1)

        self.updateShadowsArray = ShaderStructArray(
            ShadowSource, self.maxShadowUpdatesPerFrame)
        self.allShadowsArray = ShaderStructArray(
            ShadowSource, self.maxShadowMaps)

        # Create shadow compute buffer
        self._createShadowComputationBuffer()

        # Create the initial shadow state
        self.shadowComputeCamera.setTagStateKey("ShadowPassShader")
        # self.shadowComputeCamera.setInitialState(RenderState.make(
            # ColorWriteAttrib.make(ColorWriteAttrib.C_off),
            # ColorWriteAttrib.make(ColorWriteAttrib.C_rgb),
            # DepthWriteAttrib.make(DepthWriteAttrib.M_on),
            # CullFaceAttrib.make(CullFaceAttrib.MCullNone),
            # 100))

        self._createTagStates()

        self.shadowScene.setTag("ShadowPassShader", "Default")

        # Create debug overlay
        self._createDebugTexts()

        # Disable buffer on start
        self.shadowComputeTarget.setActive(False)

        # Bind arrays
        self.updateShadowsArray.bindTo(self.shadowScene, "updateSources")
        self.updateShadowsArray.bindTo(
            self.shadowComputeTarget, "updateSources")

        # Set initial inputs
        for target in [self.shadowComputeTarget, self.shadowScene]:
            target.setShaderInput("numUpdates", self.numShadowUpdatesPTA)

        self.lightingComputator = None
        self.lightCuller = None
        self.skip = 0
        self.skipRate = 0
Beispiel #30
0
 def __init__(self, pipeline):
     RenderStage.__init__(self, pipeline)
     self.area_tex = None
     self.search_tex = None
     self.use_reprojection = True
     self._jitter_index = PTAInt.empty_array(1)
 def _create_ptas(self):
     self._pta_grid_pos = PTALVecBase3.empty_array(1)
     self._pta_grid_size = PTAFloat.empty_array(1)
     self._pta_grid_res = PTAInt.empty_array(1)
     self._pta_grid_size[0] = self._voxel_ws
     self._pta_grid_res[0] = self._voxel_res
Beispiel #32
0
    def __init__(self, pipeline):
        """ Creates a new LightManager. It expects a RenderPipeline as parameter. """
        DebugObject.__init__(self, "LightManager")

        self.lightSlots = [None] * LightLimits.maxTotalLights
        self.shadowSourceSlots = [None] * LightLimits.maxShadowMaps

        self.queuedShadowUpdates = []
        self.renderedLights = {}

        self.pipeline = pipeline

        # Create arrays to store lights & shadow sources
        self.allLightsArray = ShaderStructArray(Light, LightLimits.maxTotalLights)
        self.updateCallbacks = []

        self.cullBounds = None
        self.shadowScene = Globals.render

        # Create atlas
        self.shadowAtlas = ShadowAtlas()
        self.shadowAtlas.setSize(self.pipeline.settings.shadowAtlasSize)
        self.shadowAtlas.create()

        self.maxShadowUpdatesPerFrame = self.pipeline.settings.maxShadowUpdatesPerFrame
        self.numShadowUpdatesPTA = PTAInt.emptyArray(1)

        self.updateShadowsArray = ShaderStructArray(
            ShadowSource, self.maxShadowUpdatesPerFrame)
        self.allShadowsArray = ShaderStructArray(
            ShadowSource, LightLimits.maxShadowMaps)

        # Create shadow compute buffer
        self._createShadowPass()
        self._createUnshadowedLightsPass()
        self._createShadowedLightsPass()

        if self.pipeline.settings.enableScattering:
            self._createScatteringPass()


        self._initLightCulling()

        # Create the initial shadow state
        self.shadowScene.setTag("ShadowPassShader", "Default")

        # Register variables & arrays
        self.pipeline.getRenderPassManager().registerDynamicVariable("shadowUpdateSources", 
            self._bindUpdateSources)
        self.pipeline.getRenderPassManager().registerDynamicVariable("allLights", 
            self._bindAllLights)
        self.pipeline.getRenderPassManager().registerDynamicVariable("allShadowSources", 
            self._bindAllSources)

        self.pipeline.getRenderPassManager().registerStaticVariable("numShadowUpdates", 
            self.numShadowUpdatesPTA)

        self._loadIESProfiles()
        self._addShaderDefines()
        self.lightingComputator = None
        self._createDebugTexts()