Exemplo n.º 1
0
class SkyAOCaptureStage(RenderStage):

    """ This stage captures the sky ao by rendering the scene from above """

    required_inputs = []
    required_pipes = []

    @property
    def produced_pipes(self):
        return {"SkyAOHeight": self.target_convert.color_tex}

    @property
    def produced_inputs(self):
        return {"SkyAOCapturePosition": self.pta_position}

    def __init__(self, pipeline):
        RenderStage.__init__(self, pipeline)
        self.pta_position = PTALVecBase3f.empty_array(1)
        self.resolution = 512
        self.capture_height = 100.0
        self.max_radius = 100.0

    def create(self):
        self.camera = Camera("SkyAOCaptureCam")
        self.cam_lens = OrthographicLens()
        self.cam_lens.set_film_size(self.max_radius, self.max_radius)
        self.cam_lens.set_near_far(0, self.capture_height)
        self.camera.set_lens(self.cam_lens)
        self.cam_node = Globals.base.render.attach_new_node(self.camera)
        self.cam_node.look_at(0, 0, -1)
        self.cam_node.set_r(0)

        self.target = self.create_target("SkyAOCapture")
        self.target.size = self.resolution
        self.target.add_depth_attachment(bits=16)
        self.target.prepare_render(self.cam_node)

        self.target_convert = self.create_target("ConvertDepth")
        self.target_convert.size = self.resolution
        self.target_convert.add_color_attachment(bits=(16, 0, 0, 0))
        self.target_convert.prepare_buffer()

        self.target_convert.set_shader_inputs(
            DepthTex=self.target.depth_tex,
            position=self.pta_position)

        # Register camera
        self._pipeline.tag_mgr.register_camera("shadow", self.camera)

    def update(self):
        snap_size = self.max_radius / self.resolution
        cam_pos = Globals.base.camera.get_pos(Globals.base.render)
        self.cam_node.set_pos(
            cam_pos.x - cam_pos.x % snap_size,
            cam_pos.y - cam_pos.y % snap_size,
            self.capture_height / 2.0)
        self.pta_position[0] = self.cam_node.get_pos()

    def reload_shaders(self):
        self.target_convert.shader = self.load_plugin_shader("convert_depth.frag.glsl")
Exemplo n.º 2
0
class PbCameraNode(NodePath):
    """Pybullet-compatible camera node wrapper
    """

    Z2Y = Mat4(1, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 1)

    def __init__(self, render: NodePath):
        self._camera = Camera('pb_camera')
        self._lens = MatrixLens()
        self._camera.set_lens(self._lens)
        super().__init__(self._camera)
        self.reparent_to(render)

    def set_active(self, active: bool):
        self._camera.set_active(active)

    def is_active(self):
        return self._camera.is_active()

    def update(self, pb_camera):
        self.set_mat(self.Z2Y * Mat4(*pb_camera.pose_mat))
        mat = np.asarray(pb_camera.proj_mat).reshape(4, 4)
        m22, m32 = -mat[2, 2], -mat[3, 2]
        zfar = (2.0 * m32) / (2.0 * m22 - 2.0)
        znear = ((m22 - 1.0) * zfar) / (m22 + 1.0)
        self._lens.set_near_far(znear, zfar)
        self._lens.set_user_mat(self.Z2Y * Mat4(*pb_camera.proj_mat))
Exemplo n.º 3
0
class SkyAOCaptureStage(RenderStage):
    """ This stage captures the sky ao by rendering the scene from above """

    required_inputs = []
    required_pipes = []

    @property
    def produced_pipes(self):
        return {"SkyAOHeight": self.target_convert.color_tex}

    @property
    def produced_inputs(self):
        return {"SkyAOCapturePosition": self.pta_position}

    def __init__(self, pipeline):
        RenderStage.__init__(self, pipeline)
        self.pta_position = PTALVecBase3f.empty_array(1)
        self.resolution = 512
        self.capture_height = 100.0
        self.max_radius = 100.0

    def create(self):
        self.camera = Camera("SkyAOCaptureCam")
        self.cam_lens = OrthographicLens()
        self.cam_lens.set_film_size(self.max_radius, self.max_radius)
        self.cam_lens.set_near_far(0, self.capture_height)
        self.camera.set_lens(self.cam_lens)
        self.cam_node = Globals.base.render.attach_new_node(self.camera)
        self.cam_node.look_at(0, 0, -1)
        self.cam_node.set_r(0)

        self.target = self.create_target("SkyAOCapture")
        self.target.size = self.resolution
        self.target.add_depth_attachment(bits=16)
        self.target.prepare_render(self.cam_node)

        self.target_convert = self.create_target("ConvertDepth")
        self.target_convert.size = self.resolution
        self.target_convert.add_color_attachment(bits=(16, 0, 0, 0))
        self.target_convert.prepare_buffer()

        self.target_convert.set_shader_inputs(DepthTex=self.target.depth_tex,
                                              position=self.pta_position)

        # Register camera
        self._pipeline.tag_mgr.register_camera("shadow", self.camera)

    def update(self):
        snap_size = self.max_radius / self.resolution
        cam_pos = Globals.base.camera.get_pos(Globals.base.render)
        self.cam_node.set_pos(cam_pos.x - cam_pos.x % snap_size,
                              cam_pos.y - cam_pos.y % snap_size,
                              self.capture_height / 2.0)
        self.pta_position[0] = self.cam_node.get_pos()

    def reload_shaders(self):
        self.target_convert.shader = self.load_plugin_shader(
            "convert_depth.frag.glsl")
Exemplo n.º 4
0
    def create_camera(self, name, projection_mat):
        """
        Create a camera with the given projection matrix.
        """

        cam_node = Camera(name)
        lens = MatrixLens()
        lens.set_user_mat(projection_mat)
        cam_node.set_lens(lens)
        return cam_node
Exemplo n.º 5
0
 def _make_fullscreen_cam(self):
     """ Creates an orthographic camera for the buffer """
     buffer_cam = Camera("BufferCamera")
     lens = OrthographicLens()
     lens.set_film_size(2, 2)
     lens.set_film_offset(0, 0)
     lens.set_near_far(-100, 100)
     buffer_cam.set_lens(lens)
     buffer_cam.set_cull_bounds(OmniBoundingVolume())
     self._camera = self._node.attach_new_node(buffer_cam)
     self._region.set_camera(self._camera)
 def _make_fullscreen_cam(self):
     """ Creates an orthographic camera for the buffer """
     buffer_cam = Camera("BufferCamera")
     lens = OrthographicLens()
     lens.set_film_size(2, 2)
     lens.set_film_offset(0, 0)
     lens.set_near_far(-100, 100)
     buffer_cam.set_lens(lens)
     buffer_cam.set_cull_bounds(OmniBoundingVolume())
     self._camera = self._node.attach_new_node(buffer_cam)
     self._region.set_camera(self._camera)
Exemplo n.º 7
0
class ForwardStage(RenderStage):
    """ Forward shading stage, which first renders all forward objects,
    and then merges them with the scene """

    required_inputs = [
        "DefaultEnvmap", "PrefilteredBRDF", "PrefilteredCoatBRDF", "EnvProbes"
    ]
    required_pipes = [
        "SceneDepth", "ShadedScene", "PerCellProbes", "CellIndices"
    ]

    @property
    def produced_pipes(self):
        return {"ShadedScene": self.target_merge.color_tex}

    def create(self):
        self.forward_cam = Camera("ForwardShadingCam")
        self.forward_cam.set_lens(Globals.base.camLens)
        self.forward_cam_np = Globals.base.camera.attach_new_node(
            self.forward_cam)

        self.target = self.create_target("ForwardShading")
        self.target.add_color_attachment(bits=16, alpha=True)
        self.target.add_depth_attachment(bits=32)
        self.target.prepare_render(self.forward_cam_np)

        self.target.set_clear_color(0, 0, 0, 0)

        self._pipeline.tag_mgr.register_camera("forward", self.forward_cam)

        self.target_merge = self.create_target("MergeWithDeferred")
        self.target_merge.add_color_attachment(bits=16)
        self.target_merge.prepare_buffer()
        self.target_merge.set_shader_input("ForwardDepth",
                                           self.target.depth_tex)
        self.target_merge.set_shader_input("ForwardColor",
                                           self.target.color_tex)

    def set_shader_input(self, *args):
        Globals.base.render.set_shader_input(*args)
        RenderStage.set_shader_input(self, *args)

    def reload_shaders(self):
        self.target_merge.shader = self.load_plugin_shader(
            "merge_with_deferred.frag.glsl")
Exemplo n.º 8
0
class ForwardStage(RenderStage):

    """ Forward shading stage, which first renders all forward objects,
    and then merges them with the scene """

    required_inputs = ["DefaultEnvmap", "PrefilteredBRDF", "PrefilteredCoatBRDF"]
    required_pipes = ["SceneDepth", "ShadedScene", "CellIndices"]

    @property
    def produced_pipes(self):
        return {"ShadedScene": self.target_merge.color_tex}

    def create(self):
        self.forward_cam = Camera("ForwardShadingCam")
        self.forward_cam.set_lens(Globals.base.camLens)
        self.forward_cam_np = Globals.base.camera.attach_new_node(self.forward_cam)

        self.target = self.create_target("ForwardShading")
        self.target.add_color_attachment(bits=16, alpha=True)
        self.target.add_depth_attachment(bits=32)
        self.target.prepare_render(self.forward_cam_np)
        self.target.set_clear_color(0, 0, 0, 0)

        self._pipeline.tag_mgr.register_camera("forward", self.forward_cam)

        self.target_merge = self.create_target("MergeWithDeferred")
        self.target_merge.add_color_attachment(bits=16)
        self.target_merge.prepare_buffer()
        self.target_merge.set_shader_inputs(
            ForwardDepth=self.target.depth_tex,
            ForwardColor=self.target.color_tex)

    def set_shader_input(self, *args):
        Globals.base.render.set_shader_input(*args)
        RenderStage.set_shader_input(self, *args)

    def set_shader_inputs(self, **kwargs):
        Globals.base.render.set_shader_inputs(**kwargs)
        RenderStage.set_shader_inputs(self, **kwargs)

    def reload_shaders(self):
        self.target_merge.shader = self.load_plugin_shader("merge_with_deferred.frag.glsl")
Exemplo n.º 9
0
class ForwardInjectionStage(RenderStage):
    """ Forward shading stage, which renders all forward objects and injects
    them into the clustered grid. Also produces a depth map which is used
    later on in the shading stage. """

    required_inputs = []
    required_pipes = []

    @property
    def produced_pipes(self):
        return {}

    def create(self):
        self.forward_cam = Camera("ForwardShadingCam")
        self.forward_cam.set_lens(Globals.base.camLens)
        self.forward_cam_np = Globals.base.camera.attach_new_node(
            self.forward_cam)

        self.target = self.create_target("ForwardShading")
        self.target.add_color_attachment(bits=16, alpha=True)
        self.target.add_depth_attachment(bits=32)
        self.target.prepare_render(self.forward_cam_np)

        self.target.set_clear_color(0, 0, 0, 0)

        self._pipeline.tag_mgr.register_camera("forward", self.forward_cam)

        self.target_merge = self.create_target("MergeWithDeferred")
        self.target_merge.add_color_attachment(bits=16)
        self.target_merge.prepare_buffer()
        self.target_merge.set_shader_input("ForwardDepth",
                                           self.target.depth_tex)
        self.target_merge.set_shader_input("ForwardColor",
                                           self.target.color_tex)

    def set_shader_input(self, *args):
        Globals.base.render.set_shader_input(*args)
        RenderStage.set_shader_input(self, *args)

    def reload_shaders(self):
        self.target_merge.shader = self.load_plugin_shader(
            "merge_with_deferred.frag.glsl")
Exemplo n.º 10
0
    def init(self):
        for i in range(self._max_updates):
            camera = Camera("ShadowCam-" + str(i))
            camera.set_lens(MatrixLens())
            camera.set_active(False)
            camera.set_scene(self._scene_parent)
            self._tag_state_mgr.register_shadow_camera(camera)
            self._camera_nps.append(self._scene_parent.attach_new_node(camera))
            self._cameras.append(camera)

            region = self._atlas_graphics_output.make_display_region()
            region.set_sort(1000)
            region.set_clear_depth_active(True)
            region.set_clear_depth(1.0)
            region.set_clear_color_active(False)
            region.set_camera(self._camera_nps[i])
            region.set_active(False)
            self._display_regions.append(region)

        self._atlas = ShadowAtlas(self._atlas_size)
Exemplo n.º 11
0
    def init(self):
        for i in range(self._max_updates):
            camera = Camera("ShadowCam-" + str(i))
            camera.set_lens(MatrixLens())
            camera.set_active(False)
            camera.set_scene(self._scene_parent)
            self._tag_state_mgr.register_camera("shadow", camera)
            self._camera_nps.append(self._scene_parent.attach_new_node(camera))
            self._cameras.append(camera)

            region = self._atlas_graphics_output.make_display_region()
            region.set_sort(1000)
            region.set_clear_depth_active(True)
            region.set_clear_depth(1.0)
            region.set_clear_color_active(False)
            region.set_camera(self._camera_nps[i])
            region.set_active(False)
            self._display_regions.append(region)

        self._atlas = ShadowAtlas(self._atlas_size)
Exemplo n.º 12
0
class ForwardInjectionStage(RenderStage):

    """ Forward shading stage, which renders all forward objects and injects
    them into the clustered grid. Also produces a depth map which is used
    later on in the shading stage. """

    required_inputs = []
    required_pipes = []

    @property
    def produced_pipes(self):
        return {}

    def create(self):
        self.forward_cam = Camera("ForwardShadingCam")
        self.forward_cam.set_lens(Globals.base.camLens)
        self.forward_cam_np = Globals.base.camera.attach_new_node(self.forward_cam)

        self.target = self.create_target("ForwardShading")
        self.target.add_color_attachment(bits=16, alpha=True)
        self.target.add_depth_attachment(bits=32)
        self.target.prepare_render(self.forward_cam_np)

        self.target.set_clear_color(0, 0, 0, 0)

        self._pipeline.tag_mgr.register_camera("forward", self.forward_cam)

        self.target_merge = self.create_target("MergeWithDeferred")
        self.target_merge.add_color_attachment(bits=16)
        self.target_merge.prepare_buffer()
        self.target_merge.set_shader_input("ForwardDepth", self.target.depth_tex)
        self.target_merge.set_shader_input("ForwardColor", self.target.color_tex)

    def set_shader_input(self, *args):
        Globals.base.render.set_shader_input(*args)
        RenderStage.set_shader_input(self, *args)

    def reload_shaders(self):
        self.target_merge.shader = self.load_plugin_shader("merge_with_deferred.frag.glsl")
Exemplo n.º 13
0
    def __take_hd_screenshot(self):
        mx, my, mz = self.__map.data.shape

        # find the optimal zoom fit
        max_width = max(mx, my)
        max_height = max(mx, mz)
        tex = Texture()
        width = 4096
        height = 4096
        ss_buf = self._services.graphics.window.win.make_texture_buffer('hd_screenshot_buff', width, height, tex, True)

        cam = Camera('hd_cam')
        cam.set_lens(self._services.graphics.window.camLens.make_copy())
        cam.get_lens().set_aspect_ratio(width / height)
        np_cam = NodePath(cam)
        np_cam.reparent_to(self.__world)
        x, y, z = self.__world.get_pos()

        if mz > 1:
            # 3D map
            np_cam.set_pos(x - mx * 2.1, y - max_height * 3.6, z)
            np_cam.set_h(-30)
        else:
            # 2D map
            np_cam.set_pos(x, y, z + max_width * 2 + 1)
            np_cam.set_p(-90)

        ss_cam = self._services.graphics.window.make_camera(ss_buf, useCamera=np_cam)
        ss_scene = self._services.graphics.window.render
        ss_cam.node().set_scene(ss_scene)
        self._services.graphics.window.graphicsEngine.render_frame()
        tex = ss_buf.get_texture()
        ss_buf.set_active(False)

        self._services.resources.screenshots_dir.append(lambda fn: tex.write(fn))
        self._services.graphics.window.graphicsEngine.remove_window(ss_buf)
class PSSMSceneShadowStage(RenderStage):

    """ This stage creates the shadow map which covers the whole important part
    of the scene. This is required because the shadow cascades only cover the
    view frustum, but many plugins (VXGI, EnvMaps) require a shadow map. """

    required_inputs = []
    required_pipes = []

    def __init__(self, pipeline):
        RenderStage.__init__(self, pipeline)
        self.resolution = 2048
        self.sun_vector = Vec3(0, 0, 1)
        self.sun_distance = 10.0
        self.pta_mvp = PTAMat4.empty_array(1)
        self.focus = None

        # Store last focus entirely for the purpose of being able to see
        # it in the debugger
        self.last_focus = None

    @property
    def produced_inputs(self):
        return {"PSSMSceneSunShadowMVP": self.pta_mvp}

    @property
    def produced_pipes(self):
        return {"PSSMSceneSunShadowMapPCF": (self.target.depth_tex, self.make_pcf_state())}

    def make_pcf_state(self):
        state = SamplerState()
        state.set_minfilter(SamplerState.FT_shadow)
        state.set_magfilter(SamplerState.FT_shadow)
        return state

    def request_focus(self, focus_point, focus_size):
        self.focus = (focus_point, focus_size)
        self.last_focus = self.focus

    @property
    def mvp(self):
        return Globals.base.render.get_transform(self.cam_node).get_mat() * \
            self.cam_lens.get_projection_mat()

    def update(self):
        if self._pipeline.task_scheduler.is_scheduled("pssm_scene_shadows"):
            if self.focus is None:
                # When no focus is set, there is no point in rendering the shadow map
                self.target.active = False
            else:
                focus_point, focus_size = self.focus

                self.cam_lens.set_near_far(0.0, 2 * (focus_size + self.sun_distance))
                self.cam_lens.set_film_size(2 * focus_size, 2 * focus_size)
                self.cam_node.set_pos(
                    focus_point + self.sun_vector * (self.sun_distance + focus_size))
                self.cam_node.look_at(focus_point)

                snap_shadow_map(self.mvp, self.cam_node, self.resolution)
                self.target.active = True
                self.pta_mvp[0] = self.mvp

                self.focus = None
        else:
            self.target.active = False

    def create(self):
        self.camera = Camera("PSSMSceneSunShadowCam")
        self.cam_lens = OrthographicLens()
        self.cam_lens.set_film_size(400, 400)
        self.cam_lens.set_near_far(100.0, 1800.0)
        self.camera.set_lens(self.cam_lens)
        self.cam_node = Globals.base.render.attach_new_node(self.camera)

        self.target = self.create_target("ShadowMap")
        self.target.size = self.resolution
        self.target.add_depth_attachment(bits=32)
        self.target.prepare_render(self.cam_node)

        # Register shadow camera
        self._pipeline.tag_mgr.register_camera("shadow", self.camera)

    def set_shader_input(self, *args):
        Globals.render.set_shader_input(*args)

    def set_shader_inputs(self, **kwargs):
        Globals.render.set_shader_inputs(**kwargs)
Exemplo n.º 15
0
class CloudStage(RenderStage):

    """ This stage handles the volumetric cloud rendering """

    required_pipes = ["ShadedScene", "GBuffer", "ScatteringIBLDiffuse"]

    def __init__(self, pipeline):
        RenderStage.__init__(self, "CloudStage", pipeline)
        self._voxel_res_xy = 256
        self._voxel_res_z = 16

    def get_produced_pipes(self):
        return {"ShadedScene": self._target_apply_clouds["color"]}

    def get_produced_defines(self):
        return {"CLOUD_RES_XY": self._voxel_res_xy, "CLOUD_RES_Z": self._voxel_res_z}

    def create(self):

        # Construct the voxel texture
        self._cloud_voxels = Image.create_3d(
            "CloudVoxels",
            self._voxel_res_xy,
            self._voxel_res_xy,
            self._voxel_res_z,
            Texture.T_unsigned_byte,
            Texture.F_rgba8,
        )
        self._cloud_voxels.get_texture().set_wrap_u(SamplerState.WM_repeat)
        self._cloud_voxels.get_texture().set_wrap_v(SamplerState.WM_repeat)
        self._cloud_voxels.get_texture().set_wrap_w(SamplerState.WM_border_color)
        self._cloud_voxels.get_texture().set_border_color(Vec4(0, 0, 0, 0))
        # self._cloud_voxels.get_texture().set_border_color(Vec4(1, 0, 0, 1))

        # Construct the target which populates the voxel texture
        self._grid_target = self._create_target("Clouds:CreateGrid")
        self._grid_target.set_size(self._voxel_res_xy, self._voxel_res_xy)
        self._grid_target.prepare_offscreen_buffer()
        self._grid_target.set_shader_input("CloudVoxels", self._cloud_voxels.get_texture())

        # Construct the target which shades the voxels
        self._shade_target = self._create_target("Clouds:ShadeVoxels")
        self._shade_target.set_size(self._voxel_res_xy, self._voxel_res_xy)
        self._shade_target.prepare_offscreen_buffer()
        self._shade_target.set_shader_input("CloudVoxels", self._cloud_voxels.get_texture())
        self._shade_target.set_shader_input("CloudVoxelsDest", self._cloud_voxels.get_texture())

        self._particle_target = self._create_target("Clouds:RenderClouds")
        self._particle_target.set_half_resolution()
        self._particle_target.add_color_texture(bits=16)
        self._particle_target.prepare_offscreen_buffer()
        self._particle_target.set_shader_input("CloudVoxels", self._cloud_voxels.get_texture())

        # self._make_particle_scene()

        self._target_apply_clouds = self._create_target("Clouds:ApplyClouds")
        self._target_apply_clouds.add_color_texture(bits=16)
        self._target_apply_clouds.prepare_offscreen_buffer()

        self._target_apply_clouds.set_shader_input("CloudsTex", self._particle_target["color"])

    def _make_particle_scene(self):

        # Create a new scene root
        self._particle_scene = Globals.base.render.attach_new_node("CloudParticles")
        self._particle_scene.hide(self._pipeline.tag_mgr.get_gbuffer_mask())
        self._particle_scene.hide(self._pipeline.tag_mgr.get_shadow_mask())
        self._particle_scene.hide(self._pipeline.tag_mgr.get_voxelize_mask())

        cm = CardMaker("")
        cm.set_frame(-1.0, 1.0, -1.0, 1.0)
        cm.set_has_normals(False)
        cm.set_has_uvs(False)
        card_node = cm.generate()
        card_node.set_bounds(OmniBoundingVolume())
        card_node.set_final(True)
        self._particle_np = self._particle_scene.attach_new_node(card_node)
        self._particle_np.set_shader_input("CloudVoxels", self._cloud_voxels.get_texture())
        self._particle_np.set_instance_count(self._voxel_res_xy * self._voxel_res_xy * self._voxel_res_z)
        self._particle_np.set_transparency(TransparencyAttrib.M_multisample, 1000000)
        self._particle_scene.set_transparency(TransparencyAttrib.M_multisample, 1000000)

        self._particle_cam = Camera("CloudParticleCam")
        self._particle_cam.set_lens(Globals.base.camLens)
        self._particle_cam_np = self._particle_scene.attach_new_node(self._particle_cam)

        cloud_particle_mask = BitMask32.bit(16)
        self._particle_cam.set_camera_mask(cloud_particle_mask)
        render.hide(cloud_particle_mask)
        self._particle_scene.show_through(cloud_particle_mask)

        self._particle_target = self._create_target("Clouds:RenderParticles")
        self._particle_target.add_color_texture(bits=16)
        self._particle_target.set_source(self._particle_cam_np, Globals.base.win)
        self._particle_target.set_enable_transparency(True)
        self._particle_target.prepare_scene_render()
        self._particle_target.set_clear_color(True, color=Vec4(0, 0, 0, 0))

    def update(self):
        pass

    #     self._particle_cam_np.set_transform(
    #         Globals.base.camera.get_transform(Globals.base.render))

    def set_shaders(self):
        self._grid_target.set_shader(self._load_plugin_shader("GenerateClouds.frag.glsl"))
        self._target_apply_clouds.set_shader(self._load_plugin_shader("ApplyClouds.frag.glsl"))
        self._shade_target.set_shader(self._load_plugin_shader("ShadeClouds.frag.glsl"))

        self._particle_target.set_shader(self._load_plugin_shader("RenderClouds.frag.glsl"))
Exemplo n.º 16
0
class VoxelizationStage(RenderStage):
    """ This stage voxelizes the whole scene """

    required_inputs = ["DefaultEnvmap", "AllLightsData", "maxLightIndex"]
    required_pipes = []

    # The different states of voxelization
    S_disabled = 0
    S_voxelize_x = 1
    S_voxelize_y = 2
    S_voxelize_z = 3
    S_gen_mipmaps = 4

    def __init__(self, pipeline):
        RenderStage.__init__(self, pipeline)
        self.voxel_resolution = 256
        self.voxel_world_size = -1
        self.state = self.S_disabled
        self.create_ptas()

    def set_grid_position(self, pos):
        self.pta_next_grid_pos[0] = pos

    def create_ptas(self):
        self.pta_next_grid_pos = PTALVecBase3.empty_array(1)
        self.pta_grid_pos = PTALVecBase3.empty_array(1)

    @property
    def produced_inputs(self):
        return {"voxelGridPosition": self.pta_grid_pos}

    @property
    def produced_pipes(self):
        return {"SceneVoxels": self.voxel_grid}

    def create(self):
        # Create the voxel grid used to generate the voxels
        self.voxel_temp_grid = Image.create_3d("VoxelsTemp",
                                               self.voxel_resolution,
                                               self.voxel_resolution,
                                               self.voxel_resolution, "RGBA8")
        self.voxel_temp_grid.set_clear_color(Vec4(0))
        self.voxel_temp_nrm_grid = Image.create_3d("VoxelsTemp",
                                                   self.voxel_resolution,
                                                   self.voxel_resolution,
                                                   self.voxel_resolution,
                                                   "R11G11B10")
        self.voxel_temp_nrm_grid.set_clear_color(Vec4(0))

        # Create the voxel grid which is a copy of the temporary grid, but stable
        self.voxel_grid = Image.create_3d("Voxels", self.voxel_resolution,
                                          self.voxel_resolution,
                                          self.voxel_resolution, "RGBA8")
        self.voxel_grid.set_clear_color(Vec4(0))
        self.voxel_grid.set_minfilter(SamplerState.FT_linear_mipmap_linear)

        # Create the camera for voxelization
        self.voxel_cam = Camera("VoxelizeCam")
        self.voxel_cam.set_camera_mask(
            self._pipeline.tag_mgr.get_voxelize_mask())
        self.voxel_cam_lens = OrthographicLens()
        self.voxel_cam_lens.set_film_size(-2.0 * self.voxel_world_size,
                                          2.0 * self.voxel_world_size)
        self.voxel_cam_lens.set_near_far(0.0, 2.0 * self.voxel_world_size)
        self.voxel_cam.set_lens(self.voxel_cam_lens)
        self.voxel_cam_np = Globals.base.render.attach_new_node(self.voxel_cam)
        self._pipeline.tag_mgr.register_camera("voxelize", self.voxel_cam)

        # Create the voxelization target
        self.voxel_target = self.create_target("VoxelizeScene")
        self.voxel_target.size = self.voxel_resolution
        self.voxel_target.prepare_render(self.voxel_cam_np)

        # Create the target which copies the voxel grid
        self.copy_target = self.create_target("CopyVoxels")
        self.copy_target.size = self.voxel_resolution
        self.copy_target.prepare_buffer()

        # TODO! Does not work with the new render target yet - maybe add option
        # to post process region for instances?
        self.copy_target.instance_count = self.voxel_resolution
        self.copy_target.set_shader_input("SourceTex", self.voxel_temp_grid)
        self.copy_target.set_shader_input("DestTex", self.voxel_grid)

        # Create the target which generates the mipmaps
        self.mip_targets = []
        mip_size, mip = self.voxel_resolution, 0
        while mip_size > 1:
            mip_size, mip = mip_size // 2, mip + 1
            mip_target = self.create_target("GenMipmaps:" + str(mip))
            mip_target.size = mip_size
            mip_target.prepare_buffer()
            mip_target.instance_count = mip_size
            mip_target.set_shader_input("SourceTex", self.voxel_grid)
            mip_target.set_shader_input("sourceMip", mip - 1)
            mip_target.set_shader_input("DestTex", self.voxel_grid, False,
                                        True, -1, mip, 0)
            self.mip_targets.append(mip_target)

        # Create the initial state used for rendering voxels
        initial_state = NodePath("VXGIInitialState")
        initial_state.set_attrib(
            CullFaceAttrib.make(CullFaceAttrib.M_cull_none), 100000)
        initial_state.set_attrib(DepthTestAttrib.make(DepthTestAttrib.M_none),
                                 100000)
        initial_state.set_attrib(ColorWriteAttrib.make(ColorWriteAttrib.C_off),
                                 100000)
        self.voxel_cam.set_initial_state(initial_state.get_state())

        Globals.base.render.set_shader_input("voxelGridPosition",
                                             self.pta_next_grid_pos)
        Globals.base.render.set_shader_input("VoxelGridDest",
                                             self.voxel_temp_grid)

    def update(self):
        self.voxel_cam_np.show()
        self.voxel_target.active = True
        self.copy_target.active = False

        for target in self.mip_targets:
            target.active = False

        # Voxelization disable
        if self.state == self.S_disabled:
            self.voxel_cam_np.hide()
            self.voxel_target.active = False

        # Voxelization from X-Axis
        elif self.state == self.S_voxelize_x:
            # Clear voxel grid
            self.voxel_temp_grid.clear_image()
            self.voxel_cam_np.set_pos(self.pta_next_grid_pos[0] +
                                      Vec3(self.voxel_world_size, 0, 0))
            self.voxel_cam_np.look_at(self.pta_next_grid_pos[0])

        # Voxelization from Y-Axis
        elif self.state == self.S_voxelize_y:
            self.voxel_cam_np.set_pos(self.pta_next_grid_pos[0] +
                                      Vec3(0, self.voxel_world_size, 0))
            self.voxel_cam_np.look_at(self.pta_next_grid_pos[0])

        # Voxelization from Z-Axis
        elif self.state == self.S_voxelize_z:
            self.voxel_cam_np.set_pos(self.pta_next_grid_pos[0] +
                                      Vec3(0, 0, self.voxel_world_size))
            self.voxel_cam_np.look_at(self.pta_next_grid_pos[0])

        # Generate mipmaps
        elif self.state == self.S_gen_mipmaps:
            self.voxel_target.active = False
            self.copy_target.active = True
            self.voxel_cam_np.hide()

            for target in self.mip_targets:
                target.active = True

            # As soon as we generate the mipmaps, we need to update the grid position
            # as well
            self.pta_grid_pos[0] = self.pta_next_grid_pos[0]

    def reload_shaders(self):
        self.copy_target.shader = self.load_plugin_shader(
            "/$$rp/shader/default_post_process_instanced.vert.glsl",
            "copy_voxels.frag.glsl")
        mip_shader = self.load_plugin_shader(
            "/$$rp/shader/default_post_process_instanced.vert.glsl",
            "generate_mipmaps.frag.glsl")
        for target in self.mip_targets:
            target.shader = mip_shader

    def set_shader_input(self, *args):
        Globals.render.set_shader_input(*args)
class PSSMSceneShadowStage(RenderStage):

    """ This stage creates the shadow map which covers the whole important part
    of the scene. This is required because the shadow cascades only cover the
    view frustum, but many plugins (VXGI, EnvMaps) require a shadow map. """

    required_inputs = []
    required_pipes = []

    def __init__(self, pipeline):
        RenderStage.__init__(self, pipeline)
        self.resolution = 2048
        self.sun_vector = Vec3(0, 0, 1)
        self.pta_mvp = PTAMat4.empty_array(1)

    @property
    def produced_inputs(self):
        return {"PSSMSceneSunShadowMVP": self.pta_mvp}

    @property
    def produced_pipes(self):
        return {"PSSMSceneSunShadowMapPCF": (self.target.depth_tex, self.make_pcf_state())}

    def make_pcf_state(self):
        state = SamplerState()
        state.set_minfilter(SamplerState.FT_shadow)
        state.set_magfilter(SamplerState.FT_shadow)
        return state

    @property
    def mvp(self):
        return Globals.base.render.get_transform(self.cam_node).get_mat() * \
            self.cam_lens.get_projection_mat()

    def update(self):
        if self._pipeline.task_scheduler.is_scheduled("pssm_scene_shadows"):
            cam_pos = Globals.base.cam.get_pos(Globals.base.render)
            self.cam_node.set_pos(cam_pos + self.sun_vector * 900)
            self.cam_node.look_at(cam_pos)

            snap_shadow_map(self.mvp, self.cam_node, self.resolution)

            self.target.active = True
            self.pta_mvp[0] = self.mvp
        else:
            self.target.active = False

    def create(self):
        self.camera = Camera("PSSMSceneSunShadowCam")
        self.cam_lens = OrthographicLens()
        self.cam_lens.set_film_size(400, 400)
        self.cam_lens.set_near_far(100.0, 1800.0)
        self.camera.set_lens(self.cam_lens)
        self.cam_node = Globals.base.render.attach_new_node(self.camera)

        self.target = self.create_target("ShadowMap")
        self.target.size = self.resolution
        self.target.add_depth_attachment(bits=32)
        self.target.prepare_render(self.cam_node)

        # Register shadow camera
        self._pipeline.tag_mgr.register_shadow_camera(self.camera)

    def set_shader_input(self, *args):
        Globals.render.set_shader_input(*args)
Exemplo n.º 18
0
 def create_camera(self, name, projection_mat):
     cam_node = Camera(name)
     lens = MatrixLens()
     lens.set_user_mat(projection_mat)
     cam_node.set_lens(lens)
     return cam_node
Exemplo n.º 19
0
class VXGISunShadowStage(RenderStage):

    """ This stage creates the shadow map which covers the whole voxel grid,
    to provide sun shadows for the GI """

    required_inputs = []

    def __init__(self, pipeline):
        RenderStage.__init__(self, "VXGISunShadowStage", pipeline)
        self._resolution = 2048
        self._sun_vector = Vec3(0, 0, 1)
        self._pta_mvp = PTAMat4.empty_array(1)

    def get_produced_inputs(self):
        return {"VXGISunShadowMVP": self._pta_mvp}

    def get_produced_pipes(self):
        return {"VXGISunShadowMap": (self._target['depth'], self.make_pcf_state()) }

    def make_pcf_state(self):
        state = SamplerState()
        state.set_minfilter(SamplerState.FT_shadow)
        state.set_magfilter(SamplerState.FT_shadow)
        return state

    def set_resolution(self, res):
        self._resolution = res

    def set_sun_vector(self, direction):
        self._sun_vector = direction

        distance = 400.0
        cam_pos = Globals.base.cam.get_pos(Globals.base.render)
        self._cam_node.set_pos(cam_pos + self._sun_vector * distance)
        self._cam_node.look_at(cam_pos)

        # Compute MVP
        transform = Globals.base.render.get_transform(self._cam_node).get_mat()
        self._pta_mvp[0] = transform * self._cam_lens.get_projection_mat()

    def create(self):

        self._camera = Camera("VXGISunShadowCam")
        self._cam_lens = OrthographicLens()
        self._cam_lens.set_film_size(400, 400)
        self._cam_lens.set_near_far(0.0, 800.0)
        self._camera.set_lens(self._cam_lens)
        self._cam_node = Globals.base.render.attach_new_node(self._camera)

        self._target = self.make_target("PSSMDistShadowMap")
        self._target.set_source(self._cam_node, Globals.base.win)
        self._target.size = self._resolution
        self._target.add_depth_texture(bits=32)
        self._target.create_overlay_quad = False
        self._target.color_write = False
        self._target.prepare_scene_render()

        # Register shadow camera
        self._pipeline.tag_mgr.register_shadow_camera(self._camera)

    def set_shader_input(self, *args):
        Globals.render.set_shader_input(*args)
Exemplo n.º 20
0
class VoxelizationStage(RenderStage):

    """ This stage voxelizes the whole scene """

    required_inputs = ["DefaultEnvmap", "AllLightsData", "maxLightIndex"]
    required_pipes = []

    # The different states of voxelization
    S_disabled = 0
    S_voxelize_x = 1
    S_voxelize_y = 2
    S_voxelize_z = 3
    S_gen_mipmaps = 4

    def __init__(self, pipeline):
        RenderStage.__init__(self, pipeline)
        self.voxel_resolution = 256
        self.voxel_world_size = -1
        self.state = self.S_disabled
        self.create_ptas()

    def set_grid_position(self, pos):
        self.pta_next_grid_pos[0] = pos

    def create_ptas(self):
        self.pta_next_grid_pos = PTALVecBase3.empty_array(1)
        self.pta_grid_pos = PTALVecBase3.empty_array(1)

    @property
    def produced_inputs(self):
        return {"voxelGridPosition": self.pta_grid_pos}

    @property
    def produced_pipes(self):
        return {"SceneVoxels": self.voxel_grid}

    def create(self):
        # Create the voxel grid used to generate the voxels
        self.voxel_temp_grid = Image.create_3d(
            "VoxelsTemp", self.voxel_resolution, self.voxel_resolution,
            self.voxel_resolution, "RGBA8")
        self.voxel_temp_grid.set_clear_color(Vec4(0))
        self.voxel_temp_nrm_grid = Image.create_3d(
            "VoxelsTemp", self.voxel_resolution, self.voxel_resolution,
            self.voxel_resolution, "R11G11B10")
        self.voxel_temp_nrm_grid.set_clear_color(Vec4(0))

        # Create the voxel grid which is a copy of the temporary grid, but stable
        self.voxel_grid = Image.create_3d(
            "Voxels", self.voxel_resolution, self.voxel_resolution, self.voxel_resolution, "RGBA8")
        self.voxel_grid.set_clear_color(Vec4(0))
        self.voxel_grid.set_minfilter(SamplerState.FT_linear_mipmap_linear)

        # Create the camera for voxelization
        self.voxel_cam = Camera("VoxelizeCam")
        self.voxel_cam.set_camera_mask(self._pipeline.tag_mgr.get_voxelize_mask())
        self.voxel_cam_lens = OrthographicLens()
        self.voxel_cam_lens.set_film_size(
            -2.0 * self.voxel_world_size, 2.0 * self.voxel_world_size)
        self.voxel_cam_lens.set_near_far(0.0, 2.0 * self.voxel_world_size)
        self.voxel_cam.set_lens(self.voxel_cam_lens)
        self.voxel_cam_np = Globals.base.render.attach_new_node(self.voxel_cam)
        self._pipeline.tag_mgr.register_camera("voxelize", self.voxel_cam)

        # Create the voxelization target
        self.voxel_target = self.create_target("VoxelizeScene")
        self.voxel_target.size = self.voxel_resolution
        self.voxel_target.prepare_render(self.voxel_cam_np)

        # Create the target which copies the voxel grid
        self.copy_target = self.create_target("CopyVoxels")
        self.copy_target.size = self.voxel_resolution
        self.copy_target.prepare_buffer()

        # TODO! Does not work with the new render target yet - maybe add option
        # to post process region for instances?
        self.copy_target.instance_count = self.voxel_resolution
        self.copy_target.set_shader_input("SourceTex", self.voxel_temp_grid)
        self.copy_target.set_shader_input("DestTex", self.voxel_grid)

        # Create the target which generates the mipmaps
        self.mip_targets = []
        mip_size, mip = self.voxel_resolution, 0
        while mip_size > 1:
            mip_size, mip = mip_size // 2, mip + 1
            mip_target = self.create_target("GenMipmaps:" + str(mip))
            mip_target.size = mip_size
            mip_target.prepare_buffer()
            mip_target.instance_count = mip_size
            mip_target.set_shader_input("SourceTex", self.voxel_grid)
            mip_target.set_shader_input("sourceMip", mip - 1)
            mip_target.set_shader_input("DestTex", self.voxel_grid, False, True, -1, mip, 0)
            self.mip_targets.append(mip_target)

        # Create the initial state used for rendering voxels
        initial_state = NodePath("VXGIInitialState")
        initial_state.set_attrib(CullFaceAttrib.make(CullFaceAttrib.M_cull_none), 100000)
        initial_state.set_attrib(DepthTestAttrib.make(DepthTestAttrib.M_none), 100000)
        initial_state.set_attrib(ColorWriteAttrib.make(ColorWriteAttrib.C_off), 100000)
        self.voxel_cam.set_initial_state(initial_state.get_state())

        Globals.base.render.set_shader_input("voxelGridPosition", self.pta_next_grid_pos)
        Globals.base.render.set_shader_input("VoxelGridDest", self.voxel_temp_grid)

    def update(self):
        self.voxel_cam_np.show()
        self.voxel_target.active = True
        self.copy_target.active = False

        for target in self.mip_targets:
            target.active = False

        # Voxelization disable
        if self.state == self.S_disabled:
            self.voxel_cam_np.hide()
            self.voxel_target.active = False

        # Voxelization from X-Axis
        elif self.state == self.S_voxelize_x:
            # Clear voxel grid
            self.voxel_temp_grid.clear_image()
            self.voxel_cam_np.set_pos(
                self.pta_next_grid_pos[0] + Vec3(self.voxel_world_size, 0, 0))
            self.voxel_cam_np.look_at(self.pta_next_grid_pos[0])

        # Voxelization from Y-Axis
        elif self.state == self.S_voxelize_y:
            self.voxel_cam_np.set_pos(
                self.pta_next_grid_pos[0] + Vec3(0, self.voxel_world_size, 0))
            self.voxel_cam_np.look_at(self.pta_next_grid_pos[0])

        # Voxelization from Z-Axis
        elif self.state == self.S_voxelize_z:
            self.voxel_cam_np.set_pos(
                self.pta_next_grid_pos[0] + Vec3(0, 0, self.voxel_world_size))
            self.voxel_cam_np.look_at(self.pta_next_grid_pos[0])

        # Generate mipmaps
        elif self.state == self.S_gen_mipmaps:
            self.voxel_target.active = False
            self.copy_target.active = True
            self.voxel_cam_np.hide()

            for target in self.mip_targets:
                target.active = True

            # As soon as we generate the mipmaps, we need to update the grid position
            # as well
            self.pta_grid_pos[0] = self.pta_next_grid_pos[0]

    def reload_shaders(self):
        self.copy_target.shader = self.load_plugin_shader(
            "/$$rp/shader/default_post_process_instanced.vert.glsl", "copy_voxels.frag.glsl")
        mip_shader = self.load_plugin_shader(
            "/$$rp/shader/default_post_process_instanced.vert.glsl", "generate_mipmaps.frag.glsl")
        for target in self.mip_targets:
            target.shader = mip_shader

    def set_shader_input(self, *args):
        Globals.render.set_shader_input(*args)
class PSSMSceneShadowStage(RenderStage):

    """ This stage creates the shadow map which covers the whole important part
    of the scene. This is required because the shadow cascades only cover the
    view frustum, but many plugins (VXGI, EnvMaps) require a shadow map. """

    required_inputs = []
    required_pipes = []

    def __init__(self, pipeline):
        RenderStage.__init__(self, pipeline)
        self.resolution = 2048
        self._sun_vector = Vec3(0, 0, 1)
        self.pta_mvp = PTAMat4.empty_array(1)

    @property
    def produced_inputs(self):
        return {"PSSMSceneSunShadowMVP": self.pta_mvp}

    @property
    def produced_pipes(self):
        return {"PSSMSceneSunShadowMapPCF": (self.target.depth_tex, self.make_pcf_state())}

    def make_pcf_state(self):
        state = SamplerState()
        state.set_minfilter(SamplerState.FT_shadow)
        state.set_magfilter(SamplerState.FT_shadow)
        return state

    @property
    def sun_vector(self):
        return self._sun_vector

    @sun_vector.setter
    def sun_vector(self, direction):
        self._sun_vector = direction

        distance = 400.0
        cam_pos = Globals.base.cam.get_pos(Globals.base.render)
        self.cam_node.set_pos(cam_pos + self._sun_vector * distance)
        self.cam_node.look_at(cam_pos)

        # This snaps the source to its texel grids, so that there is no flickering
        # visible when the source moves. This works by projecting the
        # Point (0,0,0) to light space, compute the texcoord differences and
        # offset the light world space position by that.
        mvp = Mat4(self.mvp)
        base_point = mvp.xform(Point4(0, 0, 0, 1)) * 0.5 + 0.5
        texel_size = 1.0 / float(self.resolution)
        offset_x = base_point.x % texel_size
        offset_y = base_point.y % texel_size
        mvp.invert_in_place()
        new_base = mvp.xform(Point4(
            (base_point.x - offset_x) * 2.0 - 1.0,
            (base_point.y - offset_y) * 2.0 - 1.0,
            (base_point.z) * 2.0 - 1.0, 1))
        self.cam_node.set_pos(self.cam_node.get_pos() - Vec3(new_base.x, new_base.y, new_base.z))
        self.pta_mvp[0] = self.mvp

    @property
    def mvp(self):
        return Globals.base.render.get_transform(self.cam_node).get_mat() * \
            self.cam_lens.get_projection_mat()

    def create(self):

        self.camera = Camera("PSSMSceneSunShadowCam")
        self.cam_lens = OrthographicLens()
        self.cam_lens.set_film_size(200, 200)
        self.cam_lens.set_near_far(100.0, 800.0)
        self.camera.set_lens(self.cam_lens)
        self.cam_node = Globals.base.render.attach_new_node(self.camera)

        self.target = self.create_target("ShadowMap")
        self.target.size = self.resolution
        self.target.add_depth_attachment(bits=32)
        self.target.prepare_render(self.cam_node)


        # Register shadow camera
        self._pipeline.tag_mgr.register_shadow_camera(self.camera)

    def set_shader_input(self, *args):
        Globals.render.set_shader_input(*args)
Exemplo n.º 22
0
class VoxelizationStage(RenderStage):

    """ This stage voxelizes the whole scene """

    required_inputs = []
    required_pipes = []

    # The different states of voxelization
    S_disabled = 0
    S_voxelize_x = 1
    S_voxelize_y = 2
    S_voxelize_z = 3
    S_gen_mipmaps = 4

    def __init__(self, pipeline):
        RenderStage.__init__(self, "VoxelizationStage", pipeline)
        self._voxel_res = 256
        self._voxel_ws = 50.0
        self._next_grid_position = Vec3(0)
        self._state = self.S_disabled
        self._create_ptas()

    def set_state(self, state):
        self._state = state

    def set_grid_position(self, pos):
        self._next_grid_position = pos

    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

    def get_produced_inputs(self):
        return {"VoxelGridPosition": self._pta_grid_pos}

    def get_produced_pipes(self):
        return {"SceneVoxels": self._voxel_grid}

    def get_produced_defines(self):
        return {"VOXEL_GRID_RES": self._voxel_res, "VOXEL_GRID_WS_SIZE": self._voxel_ws}

    def create(self):
        # Create the voxel grid used to store the voxels
        self._voxel_grid = Image.create_3d(
            "Voxels", self._voxel_res, self._voxel_res, self._voxel_res, Texture.T_float, Texture.F_r11_g11_b10
        )
        self._voxel_grid.set_clear_color(Vec4(0))

        # Create the camera for voxelization
        self._voxel_cam = Camera("VoxelizeCam")
        self._voxel_cam.set_camera_mask(self._pipeline.tag_mgr.get_voxelize_mask())
        self._voxel_cam_lens = OrthographicLens()
        self._voxel_cam_lens.set_film_size(-self._voxel_ws, self._voxel_ws)
        self._voxel_cam_lens.set_near_far(0.0, 2.0 * self._voxel_ws)
        self._voxel_cam.set_lens(self._voxel_cam_lens)
        self._voxel_cam_np = Globals.base.render.attach_new_node(self._voxel_cam)
        self._pipeline.tag_mgr.register_voxelize_camera(self._voxel_cam)

        # Create the voxelization target
        self._voxel_target = self._create_target("VoxelizeScene")
        self._voxel_target.set_source(source_cam=self._voxel_cam_np, source_win=Globals.base.win)
        self._voxel_target.set_size(self._voxel_res, self._voxel_res)
        self._voxel_target.set_create_overlay_quad(False)
        self._voxel_target.prepare_scene_render()

        # Create the initial state used for rendering voxels
        initial_state = NodePath("VXInitialState")
        initial_state.set_attrib(CullFaceAttrib.make(CullFaceAttrib.M_cull_none), 100000)
        initial_state.set_attrib(DepthTestAttrib.make(DepthTestAttrib.M_none), 100000)
        initial_state.set_attrib(ColorWriteAttrib.make(ColorWriteAttrib.C_off), 100000)
        self._voxel_cam.set_initial_state(initial_state.get_state())

        Globals.base.render.set_shader_input("voxelGridPosition", self._pta_grid_pos)
        Globals.base.render.set_shader_input("voxelGridRes", self._pta_grid_res)
        Globals.base.render.set_shader_input("voxelGridSize", self._pta_grid_size)
        Globals.base.render.set_shader_input("VoxelGridDest", self._voxel_grid.texture)

    def update(self):
        self._voxel_cam_np.show()
        self._voxel_target.set_active(True)

        # Voxelization disable
        if self._state == self.S_disabled:
            self._voxel_cam_np.hide()
            self._voxel_target.set_active(False)

        # Voxelization from X-Axis
        elif self._state == self.S_voxelize_x:
            self._voxel_cam_np.set_pos(self._next_grid_position + Vec3(self._voxel_ws, 0, 0))
            self._voxel_cam_np.look_at(self._next_grid_position)

        # Voxelization from Y-Axis
        elif self._state == self.S_voxelize_y:
            self._voxel_cam_np.set_pos(self._next_grid_position + Vec3(0, self._voxel_ws, 0))
            self._voxel_cam_np.look_at(self._next_grid_position)

        # Voxelization from Z-Axis
        elif self._state == self.S_voxelize_z:
            self._voxel_cam_np.set_pos(self._next_grid_position + Vec3(0, 0, self._voxel_ws))
            self._voxel_cam_np.look_at(self._next_grid_position)

        # Generate mipmaps
        elif self._state == self.S_gen_mipmaps:
            self._voxel_target.set_active(False)
            self._voxel_cam_np.hide()

            # As soon as we generate the mipmaps, we need to update the grid position
            # as well
            self._pta_grid_pos[0] = self._next_grid_position

    def set_shaders(self):
        pass
Exemplo n.º 23
0
class PSSMDistShadowStage(RenderStage):

    """ This stage generates a depth map using Variance Shadow Maps for very
    distant objects. """

    required_inputs = []

    def __init__(self, pipeline):
        RenderStage.__init__(self, pipeline)
        self.resolution = 2048
        self.clip_size = 500
        self.sun_distance = 8000
        self.sun_vector = Vec3(0, 0, 1)
        self.pta_mvp = PTAMat4.empty_array(1)

    @property
    def produced_inputs(self):
        return {"PSSMDistSunShadowMapMVP": self.pta_mvp}

    @property
    def produced_pipes(self):
        return {"PSSMDistSunShadowMap": self.target_blur_h.color_tex}

    @property
    def mvp(self):
        return Globals.base.render.get_transform(self.cam_node).get_mat() * \
            self.cam_lens.get_projection_mat()

    def update(self):
        self.target.active = False
        self.target_convert.active = False
        self.target_blur_v.active = False
        self.target_blur_h.active = False

        # Query scheduled tasks
        if self._pipeline.task_scheduler.is_scheduled("pssm_distant_shadows"):

            self.target.active = True

            # Reposition camera before we capture the scene
            cam_pos = Globals.base.cam.get_pos(Globals.base.render)
            self.cam_node.set_pos(cam_pos + self.sun_vector * self.sun_distance)
            self.cam_node.look_at(cam_pos)
            self.cam_lens.set_film_size(self.clip_size, self.clip_size)

            snap_shadow_map(self.mvp, self.cam_node, self.resolution)

        if self._pipeline.task_scheduler.is_scheduled("pssm_convert_distant_to_esm"):
            self.target_convert.active = True
        if self._pipeline.task_scheduler.is_scheduled("pssm_blur_distant_vert"):
            self.target_blur_v.active = True
        if self._pipeline.task_scheduler.is_scheduled("pssm_blur_distant_horiz"):
            self.target_blur_h.active = True

            # Only update the MVP as soon as the shadow map is available
            self.pta_mvp[0] = self.mvp

    def create(self):
        self.camera = Camera("PSSMDistShadowsESM")
        self.cam_lens = OrthographicLens()
        self.cam_lens.set_film_size(12000, 12000)
        self.cam_lens.set_near_far(10.0, self.sun_distance * 2)
        self.camera.set_lens(self.cam_lens)
        self.cam_node = Globals.base.render.attach_new_node(self.camera)

        self.target = self.create_target("ShadowMap")
        self.target.size = self.resolution
        self.target.add_depth_attachment(bits=32)
        self.target.prepare_render(self.cam_node)

        self.target_convert = self.create_target("ConvertToESM")
        self.target_convert.size = self.resolution
        self.target_convert.add_color_attachment(bits=(32, 0, 0, 0))
        self.target_convert.prepare_buffer()
        self.target_convert.set_shader_input("SourceTex", self.target.depth_tex)

        self.target_blur_v = self.create_target("BlurVert")
        self.target_blur_v.size = self.resolution
        self.target_blur_v.add_color_attachment(bits=(32, 0, 0, 0))
        self.target_blur_v.prepare_buffer()
        self.target_blur_v.set_shader_input("SourceTex", self.target_convert.color_tex)
        self.target_blur_v.set_shader_input("direction", LVecBase2i(1, 0))

        self.target_blur_h = self.create_target("BlurHoriz")
        self.target_blur_h.size = self.resolution
        self.target_blur_h.add_color_attachment(bits=(32, 0, 0, 0))
        self.target_blur_h.prepare_buffer()
        self.target_blur_h.set_shader_input("SourceTex", self.target_blur_v.color_tex)
        self.target_blur_h.set_shader_input("direction", LVecBase2i(0, 1))

        # Register shadow camera
        self._pipeline.tag_mgr.register_camera("shadow", self.camera)

    def reload_shaders(self):
        self.target_convert.shader = self.load_plugin_shader("convert_to_esm.frag.glsl")
        self.target_blur_v.shader = self.load_plugin_shader("blur_esm.frag.glsl")
        self.target_blur_h.shader = self.load_plugin_shader("blur_esm.frag.glsl")

    def set_shader_input(self, *args):
        Globals.render.set_shader_input(*args)
Exemplo n.º 24
0
class PSSMDistShadowStage(RenderStage):

    """ This stage generates a depth map using Variance Shadow Maps for very
    distant objects. """

    required_inputs = []

    def __init__(self, pipeline):
        RenderStage.__init__(self, pipeline)
        self.resolution = 2048
        self.clip_size = 500
        self.sun_distance = 8000
        self.sun_vector = Vec3(0, 0, 1)
        self.pta_mvp = PTAMat4.empty_array(1)

    @property
    def produced_inputs(self):
        return {"PSSMDistSunShadowMapMVP": self.pta_mvp}

    @property
    def produced_pipes(self):
        return {"PSSMDistSunShadowMap": self.target_blur_h.color_tex}

    @property
    def mvp(self):
        return Globals.base.render.get_transform(self.cam_node).get_mat() * \
            self.cam_lens.get_projection_mat()

    def update(self):
        self.target.active = False
        self.target_convert.active = False
        self.target_blur_v.active = False
        self.target_blur_h.active = False

        # Query scheduled tasks
        if self._pipeline.task_scheduler.is_scheduled("pssm_distant_shadows"):

            self.target.active = True

            # Reposition camera before we capture the scene
            cam_pos = Globals.base.cam.get_pos(Globals.base.render)
            self.cam_node.set_pos(cam_pos + self.sun_vector * self.sun_distance)
            self.cam_node.look_at(cam_pos)
            self.cam_lens.set_film_size(self.clip_size, self.clip_size)

            snap_shadow_map(self.mvp, self.cam_node, self.resolution)

        if self._pipeline.task_scheduler.is_scheduled("pssm_convert_distant_to_esm"):
            self.target_convert.active = True
        if self._pipeline.task_scheduler.is_scheduled("pssm_blur_distant_vert"):
            self.target_blur_v.active = True
        if self._pipeline.task_scheduler.is_scheduled("pssm_blur_distant_horiz"):
            self.target_blur_h.active = True

            # Only update the MVP as soon as the shadow map is available
            self.pta_mvp[0] = self.mvp

    def create(self):
        self.camera = Camera("PSSMDistShadowsESM")
        self.cam_lens = OrthographicLens()
        self.cam_lens.set_film_size(12000, 12000)
        self.cam_lens.set_near_far(10.0, self.sun_distance * 2)
        self.camera.set_lens(self.cam_lens)
        self.cam_node = Globals.base.render.attach_new_node(self.camera)

        self.target = self.create_target("ShadowMap")
        self.target.size = self.resolution
        self.target.add_depth_attachment(bits=32)
        self.target.prepare_render(self.cam_node)

        self.target_convert = self.create_target("ConvertToESM")
        self.target_convert.size = self.resolution
        self.target_convert.add_color_attachment(bits=(32, 0, 0, 0))
        self.target_convert.prepare_buffer()
        self.target_convert.set_shader_input("SourceTex", self.target.depth_tex)

        self.target_blur_v = self.create_target("BlurVert")
        self.target_blur_v.size = self.resolution
        self.target_blur_v.add_color_attachment(bits=(32, 0, 0, 0))
        self.target_blur_v.prepare_buffer()
        self.target_blur_v.set_shader_input("SourceTex", self.target_convert.color_tex)
        self.target_blur_v.set_shader_input("direction", LVecBase2i(1, 0))

        self.target_blur_h = self.create_target("BlurHoriz")
        self.target_blur_h.size = self.resolution
        self.target_blur_h.add_color_attachment(bits=(32, 0, 0, 0))
        self.target_blur_h.prepare_buffer()
        self.target_blur_h.set_shader_input("SourceTex", self.target_blur_v.color_tex)
        self.target_blur_h.set_shader_input("direction", LVecBase2i(0, 1))

        # Register shadow camera
        self._pipeline.tag_mgr.register_camera("shadow", self.camera)

    def reload_shaders(self):
        self.target_convert.shader = self.load_plugin_shader("convert_to_esm.frag.glsl")
        self.target_blur_v.shader = self.load_plugin_shader("blur_esm.frag.glsl")
        self.target_blur_h.shader = self.load_plugin_shader("blur_esm.frag.glsl")

    def set_shader_input(self, *args):
        Globals.render.set_shader_input(*args)
Exemplo n.º 25
0
class PSSMSceneShadowStage(RenderStage):
    """ This stage creates the shadow map which covers the whole important part
    of the scene. This is required because the shadow cascades only cover the
    view frustum, but many plugins (VXGI, EnvMaps) require a shadow map. """

    required_inputs = []
    required_pipes = []

    def __init__(self, pipeline):
        RenderStage.__init__(self, pipeline)
        self.resolution = 2048
        self.sun_vector = Vec3(0, 0, 1)
        self.sun_distance = 10.0
        self.pta_mvp = PTAMat4.empty_array(1)
        self.focus = None

        # Store last focus entirely for the purpose of being able to see
        # it in the debugger
        self.last_focus = None

    @property
    def produced_inputs(self):
        return {"PSSMSceneSunShadowMVP": self.pta_mvp}

    @property
    def produced_pipes(self):
        return {
            "PSSMSceneSunShadowMapPCF":
            (self.target.depth_tex, self.make_pcf_state())
        }

    def make_pcf_state(self):
        state = SamplerState()
        state.set_minfilter(SamplerState.FT_shadow)
        state.set_magfilter(SamplerState.FT_shadow)
        return state

    def request_focus(self, focus_point, focus_size):
        self.focus = (focus_point, focus_size)
        self.last_focus = self.focus

    @property
    def mvp(self):
        return Globals.base.render.get_transform(self.cam_node).get_mat() * \
            self.cam_lens.get_projection_mat()

    def update(self):
        if self._pipeline.task_scheduler.is_scheduled("pssm_scene_shadows"):
            if self.focus is None:
                # When no focus is set, there is no point in rendering the shadow map
                self.target.active = False
            else:
                focus_point, focus_size = self.focus

                self.cam_lens.set_near_far(
                    0.0, 2 * (focus_size + self.sun_distance))
                self.cam_lens.set_film_size(2 * focus_size, 2 * focus_size)
                self.cam_node.set_pos(focus_point + self.sun_vector *
                                      (self.sun_distance + focus_size))
                self.cam_node.look_at(focus_point)

                snap_shadow_map(self.mvp, self.cam_node, self.resolution)
                self.target.active = True
                self.pta_mvp[0] = self.mvp

                self.focus = None
        else:
            self.target.active = False

    def create(self):
        self.camera = Camera("PSSMSceneSunShadowCam")
        self.cam_lens = OrthographicLens()
        self.cam_lens.set_film_size(400, 400)
        self.cam_lens.set_near_far(100.0, 1800.0)
        self.camera.set_lens(self.cam_lens)
        self.cam_node = Globals.base.render.attach_new_node(self.camera)

        self.target = self.create_target("ShadowMap")
        self.target.size = self.resolution
        self.target.add_depth_attachment(bits=32)
        self.target.prepare_render(self.cam_node)

        # Register shadow camera
        self._pipeline.tag_mgr.register_camera("shadow", self.camera)

    def set_shader_input(self, *args):
        Globals.render.set_shader_input(*args)