def build_curve(self):
        """ Rebuilds the curve based on the controll point values """
        sorted_points = sorted(self._cv_points, key=lambda v: v[0])
        first_point = sorted_points[0]
        fitter = CurveFitter()

        # Duplicate curve at the beginning
        for i in range(self._border_points):
            end_point = self._cv_points[(-i + self._border_points - 1) %
                                        len(self._cv_points)]
            end_point = first_point
            fitter.add_xyz(0.0, Vec3(0, end_point[1], 0))

        # Append the actual points
        for point in self._cv_points:
            # Clamp point x position to avoid artifacts at the beginning
            point_t = max(0.01, point[0])
            fitter.add_xyz(point_t, Vec3(point_t, point[1], 0))

        # Duplicate curve at the end
        for i in range(self._border_points):
            start_point = self._cv_points[i % len(self._cv_points)]
            start_point = first_point
            fitter.add_xyz(1.0, Vec3(1, start_point[1], 0))

        fitter.sort_points()
        fitter.wrap_hpr()
        fitter.compute_tangents(1.0)

        self._curve = fitter.make_hermite()
    def build_curve(self):
        """ Rebuilds the curve based on the controll point values """
        sorted_points = sorted(self._cv_points, key=lambda v: v[0])
        first_point = sorted_points[0]
        fitter = CurveFitter()

        # Duplicate curve at the beginning
        for i in range(self._border_points):
            end_point = self._cv_points[(-i + self._border_points - 1) % len(self._cv_points)]
            end_point = first_point
            fitter.add_xyz(0.0, Vec3(0, end_point[1], 0))

        # Append the actual points
        for point in self._cv_points:
            # Clamp point x position to avoid artifacts at the beginning
            point_t = max(0.01, point[0])
            fitter.add_xyz(point_t, Vec3(point_t, point[1], 0))

        # Duplicate curve at the end
        for i in range(self._border_points):
            start_point = self._cv_points[i % len(self._cv_points)]
            start_point = first_point
            fitter.add_xyz(1.0, Vec3(1, start_point[1], 0))

        fitter.sort_points()
        fitter.wrap_hpr()
        fitter.compute_tangents(1.0)

        self._curve = fitter.make_hermite()
Пример #3
0
    def create(self):

        if self.remove_fireflies:
            self.target_firefly = self.create_target("RemoveFireflies")
            self.target_firefly.add_color_attachment(bits=16)
            self.target_firefly.prepare_buffer()

        self.scene_target_img = Image.create_2d("BloomDownsample", 0, 0,
                                                "RGBA16")
        self.scene_target_img.set_minfilter(
            SamplerState.FT_linear_mipmap_linear)
        self.scene_target_img.set_magfilter(SamplerState.FT_linear)
        self.scene_target_img.set_wrap_u(SamplerState.WM_clamp)
        self.scene_target_img.set_wrap_v(SamplerState.WM_clamp)
        self.scene_target_img.set_clear_color(Vec4(0.1, 0.0, 0.0, 1.0))
        self.scene_target_img.clear_image()

        self.target_extract = self.create_target("ExtractBrightSpots")
        self.target_extract.prepare_buffer()
        self.target_extract.set_shader_input("DestTex", self.scene_target_img,
                                             False, True, -1, 0)

        if self.remove_fireflies:
            self.target_extract.set_shader_input("ShadedScene",
                                                 self.target_firefly.color_tex,
                                                 1000)

        self.downsample_targets = []
        self.upsample_targets = []

        # Downsample passes
        for i in range(self.num_mips):
            scale_multiplier = 2**(1 + i)
            target = self.create_target("Downsample:Step-" + str(i))
            target.size = -scale_multiplier, -scale_multiplier
            target.prepare_buffer()
            target.set_shader_input("sourceMip", i)
            target.set_shader_input("SourceTex", self.scene_target_img)
            target.set_shader_input("DestTex", self.scene_target_img, False,
                                    True, -1, i + 1)
            self.downsample_targets.append(target)

        # Upsample passes
        for i in range(self.num_mips):
            scale_multiplier = 2**(self.num_mips - i - 1)
            target = self.create_target("Upsample:Step-" + str(i))
            target.size = -scale_multiplier, -scale_multiplier
            target.prepare_buffer()
            target.set_shader_input("FirstUpsamplePass", i == 0)

            target.set_shader_input("sourceMip", self.num_mips - i)
            target.set_shader_input("SourceTex", self.scene_target_img)
            target.set_shader_input("DestTex", self.scene_target_img, False,
                                    True, -1, self.num_mips - i - 1)
            self.upsample_targets.append(target)

        self.target_apply = self.create_target("ApplyBloom")
        self.target_apply.add_color_attachment(bits=16)
        self.target_apply.prepare_buffer()
        self.target_apply.set_shader_input("BloomTex", self.scene_target_img)
Пример #4
0
 def find_and_reserve_region(self, tile_width, tile_height):
     for x in range(self._num_tiles - tile_height + 1):
         for y in range(self._num_tiles - tile_width + 1):
             if self.region_is_free(x, y, tile_width, tile_height):
                 self.reserve_region(x, y, tile_width, tile_height)
                 return LVecBase4i(x, y, tile_width, tile_height)
     print("Failed to find a free region of size", tile_width, "x", tile_height)
     return LVecBase4i(-1)
Пример #5
0
 def find_and_reserve_region(self, tile_width, tile_height):
     for x in range(self._num_tiles - tile_height + 1):
         for y in range(self._num_tiles - tile_width + 1):
             if self.region_is_free(x, y, tile_width, tile_height):
                 self.reserve_region(x, y, tile_width, tile_height)
                 return LVecBase4i(x, y, tile_width, tile_height)
     print("Failed to find a free region of size", tile_width, "x",
           tile_height)
     return LVecBase4i(-1)
Пример #6
0
    def create(self):

        if self.remove_fireflies:
            self.target_firefly = self.create_target("RemoveFireflies")
            self.target_firefly.add_color_attachment(bits=16)
            self.target_firefly.prepare_buffer()

        self.scene_target_img = Image.create_2d(
            "BloomDownsample", Globals.resolution.x, Globals.resolution.y, "R11G11B10")

        self.scene_target_img.set_minfilter(SamplerState.FT_linear_mipmap_linear)
        self.scene_target_img.set_magfilter(SamplerState.FT_linear)
        self.scene_target_img.set_wrap_u(SamplerState.WM_clamp)
        self.scene_target_img.set_wrap_v(SamplerState.WM_clamp)
        self.scene_target_img.set_clear_color(Vec4(0.1, 0.0, 0.0, 1.0))
        self.scene_target_img.clear_image()

        self.target_extract = self.create_target("ExtractBrightSpots")
        self.target_extract.prepare_buffer()
        self.target_extract.set_shader_input("DestTex", self.scene_target_img, False, True, -1, 0)

        if self.remove_fireflies:
            self.target_extract.set_shader_input("ShadedScene", self.target_firefly.color_tex, 1000)

        self.downsample_targets = []
        self.upsample_targets = []

        # Downsample passes
        for i in range(self.num_mips):
            scale_multiplier = 2 ** (1 + i)
            target = self.create_target("Downsample:Step-" + str(i))
            target.size = -scale_multiplier, -scale_multiplier
            target.prepare_buffer()
            target.set_shader_input("sourceMip", i)
            target.set_shader_input("SourceTex", self.scene_target_img)
            target.set_shader_input("DestTex", self.scene_target_img, False, True, -1, i + 1)
            self.downsample_targets.append(target)

        # Upsample passes
        for i in range(self.num_mips):
            scale_multiplier = 2 ** (self.num_mips - i - 1)
            target = self.create_target("Upsample:Step-" + str(i))
            target.size = -scale_multiplier, -scale_multiplier
            target.prepare_buffer()
            target.set_shader_input("FirstUpsamplePass", i == 0)

            target.set_shader_input("sourceMip", self.num_mips - i)
            target.set_shader_input("SourceTex", self.scene_target_img)
            target.set_shader_input("DestTex", self.scene_target_img,
                                    False, True, -1, self.num_mips - i - 1)
            self.upsample_targets.append(target)

        self.target_apply = self.create_target("ApplyBloom")
        self.target_apply.add_color_attachment(bits=16)
        self.target_apply.prepare_buffer()
        self.target_apply.set_shader_input("BloomTex", self.scene_target_img)
    def find_consecutive_slots(self, num_consecutive):
        if num_consecutive == 1:
            return self.find_slot()

        for i in range(len(self._data)):
            any_taken = False
            for k in range(num_consecutive):
                if self._data[i + k]:
                    any_taken = True
                    break
            if not any_taken:
                return i
        return -1
Пример #8
0
    def find_consecutive_slots(self, num_consecutive):
        if num_consecutive == 1:
            return self.find_slot()

        for i in range(len(self._data)):
            any_taken = False
            for k in range(num_consecutive):
                if self._data[i + k]:
                    any_taken = True
                    break
            if not any_taken:
                return i
        return -1
    def update_shadow_sources(self):
        sources_to_update = []

        for source in self._shadow_sources.begin():
            # if source and source.get_needs_update():
            # sources_to_update.append(source)
            if source:
                bounds = source.get_bounds()
                distance_to_camera = (self._camera_pos - bounds.get_center()
                                      ) - bounds.get_radius()
                if distance_to_camera < self._shadow_update_distance:
                    sources_to_update.append(source)
                else:
                    if source.has_region():
                        self._shadow_manager.get_atlas().free_region(
                            source.get_region())
                        source.clear_region()

        def get_source_score(source):
            dist = (source.get_bounds().get_center() -
                    self._camera_pos).length()
            return -dist + (10**10 if source.has_region() else 0)

        sorted_sources = list(sorted(sources_to_update, key=get_source_score))

        atlas = self._shadow_manager.get_atlas()
        update_slots = min(len(sorted_sources),
                           self._shadow_manager.get_num_update_slots_left())

        for i in range(update_slots):
            if sorted_sources[i].has_region():
                atlas.free_region(sorted_sources[i].get_region())

        for i in range(update_slots):
            source = sorted_sources[i]

            if not self._shadow_manager.add_update(source):
                print(
                    "ERROR: Shadow manager ensured update slot, but slot is taken!"
                )
                break

            region_size = atlas.get_required_tiles(source.get_resolution())
            new_region = atlas.find_and_reserve_region(region_size,
                                                       region_size)
            new_uv_region = atlas.region_to_uv(new_region)
            source.set_region(new_region, new_uv_region)
            source.set_needs_update(False)
            self.gpu_update_source(source)
Пример #10
0
    def generate_dataset_texture_into(self, dest_tex, layer_index):
        resolution_vertical = dest_tex.get_y_size()
        resolution_horizontal = dest_tex.get_x_size()

        dest = PNMImage(resolution_vertical, resolution_horizontal, 1, 65535)

        for vert in range(resolution_vertical):
            for horiz in range(resolution_horizontal):
                vert_angle = vert / (resolution_vertical-1.0)
                vert_angle = math.cos(vert_angle * math.pi) * 90.0 + 90.0
                horiz_angle = horiz / (resolution_horizontal-1.0) * 360.0
                candela = self.get_candela_value(vert_angle, horiz_angle)
                dest.set_xel(vert, horiz, candela)

        dest_tex.load(dest, layer_index, 0)
Пример #11
0
    def generate_dataset_texture_into(self, dest_tex, layer_index):
        resolution_vertical = dest_tex.get_y_size()
        resolution_horizontal = dest_tex.get_x_size()

        dest = PNMImage(resolution_vertical, resolution_horizontal, 1, 65535)

        for vert in range(resolution_vertical):
            for horiz in range(resolution_horizontal):
                vert_angle = vert / (resolution_vertical - 1.0)
                vert_angle = math.cos(vert_angle * math.pi) * 90.0 + 90.0
                horiz_angle = horiz / (resolution_horizontal - 1.0) * 360.0
                candela = self.get_candela_value(vert_angle, horiz_angle)
                dest.set_xel(vert, horiz, candela)

        dest_tex.load(dest, layer_index, 0)
Пример #12
0
 def create_stats(self):
     """ Creates the stats overlay """
     self.overlay_node = Globals.base.aspect2d.attach_new_node("Overlay")
     self.debug_lines = []
     for i in range(6):
         self.debug_lines.append(TextNode(
             pos=Vec2(0, -i * 0.046), parent=self.overlay_node, align="right", color=Vec3(1)))
    def create(self):
        self.target = self.create_target("ShadowMap")
        self.target.size = self.split_resolution * self.num_splits, self.split_resolution
        self.target.add_depth_attachment(bits=32)
        self.target.prepare_render(None)

        # Remove all unused display regions
        internal_buffer = self.target.internal_buffer
        internal_buffer.remove_all_display_regions()
        internal_buffer.get_display_region(0).set_active(False)
        internal_buffer.disable_clears()

        # Set a clear on the buffer instead on all regions
        internal_buffer.set_clear_depth(1)
        internal_buffer.set_clear_depth_active(True)

        # Prepare the display regions
        for i in range(self.num_splits):
            region = internal_buffer.make_display_region(
                i / self.num_splits, i / self.num_splits + 1 / self.num_splits,
                0, 1)
            region.set_sort(25 + i)
            region.disable_clears()
            region.set_active(True)
            self.split_regions.append(region)
Пример #14
0
    def create(self):
        self.target = self.create_target("ShadowMap")
        self.target.size = self.split_resolution * self.num_splits, self.split_resolution
        self.target.add_depth_attachment(bits=32)
        self.target.prepare_render(None)

        # Remove all unused display regions
        internal_buffer = self.target.internal_buffer
        internal_buffer.remove_all_display_regions()
        internal_buffer.get_display_region(0).set_active(False)
        internal_buffer.disable_clears()

        # Set a clear on the buffer instead on all regions
        internal_buffer.set_clear_depth(1)
        internal_buffer.set_clear_depth_active(True)

        # Prepare the display regions
        for i in range(self.num_splits):
            region = internal_buffer.make_display_region(
                i / self.num_splits,
                i / self.num_splits + 1 / self.num_splits, 0, 1)
            region.set_sort(25 + i)
            region.disable_clears()
            region.set_active(True)
            self.split_regions.append(region)
Пример #15
0
    def init_tiles(self):
        self._num_tiles = self._size // self._tile_size

        def row():
            return [False for i in range(self._num_tiles)]  # pylint: disable=unused-variable

        self._flags = [row() for j in range(self._num_tiles)]  # pylint: disable=unused-variable
    def remove_light(self, light):
        assert light is not None
        if not light.has_slot():
            print("ERROR: Could not detach light, light was not attached!")
            return

        self._lights.free_slot(light.get_slot())
        self.gpu_remove_light(light)
        light.remove_slot()

        if light.get_casts_shadows():

            for i in range(light.get_num_shadow_sources()):
                source = light.get_shadow_source(i)
                if source.has_slot():
                    self._shadow_sources.free_slot(source.get_slot())
                if source.has_region():
                    self._shadow_manager.get_atlas().free_region(
                        source.get_region())
                    source.clear_region()

            self.gpu_remove_consecutive_sources(light.get_shadow_source(0),
                                                light.get_num_shadow_sources())

            light.clear_shadow_sources()
    def _setup_camera_rig(self):
        """ Setups the cameras to render a cubemap """
        directions = (Vec3(1, 0, 0), Vec3(-1, 0, 0), Vec3(0, 1, 0),
                      Vec3(0, -1, 0), Vec3(0, 0, 1), Vec3(0, 0, -1))

        # Prepare the display regions
        for i in range(6):
            region = self.target.internal_buffer.make_display_region(
                i / 6, i / 6 + 1 / 6, 0, 1)
            region.set_sort(25 + i)
            region.set_active(True)
            region.disable_clears()

            lens = PerspectiveLens()
            lens.set_fov(90)
            lens.set_near_far(0.001, 1.0)
            camera = Camera("EnvmapCam-" + str(i), lens)
            camera_np = self.rig_node.attach_new_node(camera)
            camera_np.look_at(camera_np, directions[i])
            region.set_camera(camera_np)
            self.regions.append(region)
            self.cameras.append(camera_np)

        self.cameras[0].set_r(90)
        self.cameras[1].set_r(-90)
        self.cameras[3].set_r(180)
        self.cameras[5].set_r(180)

        # Register cameras
        for camera_np in self.cameras:
            self._pipeline.tag_mgr.register_envmap_camera(camera_np.node())
Пример #18
0
 def _create_stats(self):
     """ Creates the stats overlay """
     self._overlay_node = Globals.base.aspect2d.attach_new_node("Overlay")
     self._overlay_node.set_pos(Globals.base.get_aspect_ratio() - 0.07, 1, 1.0 - 0.07)
     self._debug_lines = []
     for i in range(5):
         self._debug_lines.append(TextNode(
             pos=Vec2(0, -i * 0.046), parent=self._overlay_node,
             pixel_size=16, align="right", color=Vec3(1)))
    def update_shadow_sources(self):
        sources_to_update = []

        for source in self._shadow_sources.begin():
            # if source and source.get_needs_update():
                # sources_to_update.append(source)
            if source:
                bounds = source.get_bounds()
                distance_to_camera = (self._camera_pos - bounds.get_center()) - bounds.get_radius()
                if distance_to_camera < self._shadow_update_distance:
                    sources_to_update.append(source)
                else:
                    if source.has_region():
                        self._shadow_manager.get_atlas().free_region(source.get_region())
                        source.clear_region()

        def get_source_score(source):
            dist = (source.get_bounds().get_center() - self._camera_pos).length()
            return -dist + (10**10 if source.has_region() else 0)

        sorted_sources = list(sorted(sources_to_update, key=get_source_score))

        atlas = self._shadow_manager.get_atlas()
        update_slots = min(
            len(sorted_sources),
            self._shadow_manager.get_num_update_slots_left())

        for i in range(update_slots):
            if sorted_sources[i].has_region():
                atlas.free_region(sorted_sources[i].get_region())

        for i in range(update_slots):
            source = sorted_sources[i]

            if not self._shadow_manager.add_update(source):
                print("ERROR: Shadow manager ensured update slot, but slot is taken!")
                break

            region_size = atlas.get_required_tiles(source.get_resolution())
            new_region = atlas.find_and_reserve_region(region_size, region_size)
            new_uv_region = atlas.region_to_uv(new_region)
            source.set_region(new_region, new_uv_region)
            source.set_needs_update(False)
            self.gpu_update_source(source)
    def create_stats(self):
        """ Creates the stats overlay """
        self.overlay_node = Globals.base.aspect2d.attach_new_node("Overlay")
        self.debug_lines = []

        num_lines = 6 if self.advanced_info else 1
        for i in range(num_lines):
            self.debug_lines.append(TextNode(
                pos=Vec2(0, -i * 0.046), parent=self.overlay_node, align="right", color=Vec3(0.7, 1, 1)))
        self.debug_lines[0].color = Vec4(1, 1, 0, 1)
Пример #21
0
 def create_stats(self):
     """ Creates the stats overlay """
     self.overlay_node = Globals.base.aspect2d.attach_new_node("Overlay")
     self.debug_lines = []
     for i in range(6):
         self.debug_lines.append(
             TextNode(pos=Vec2(0, -i * 0.046),
                      parent=self.overlay_node,
                      align="right",
                      color=Vec3(1)))
Пример #22
0
 def _create_stats(self):
     """ Creates the stats overlay """
     self._overlay_node = Globals.base.aspect2d.attach_new_node("Overlay")
     self._overlay_node.set_pos(Globals.base.get_aspect_ratio() - 0.07, 1,
                                1.0 - 0.07)
     self._debug_lines = []
     for i in range(6):
         self._debug_lines.append(
             TextNode(pos=Vec2(0, -i * 0.046),
                      parent=self._overlay_node,
                      pixel_size=16,
                      align="right",
                      color=Vec3(1)))
Пример #23
0
    def update(self):
        for i in range(len(self._queued_updates), self._max_updates):
            self._cameras[i].set_active(False)
            self._display_regions[i].set_active(False)

        for i, source in enumerate(self._queued_updates):
            self._cameras[i].set_active(True)
            self._display_regions[i].set_active(True)
            self._cameras[i].get_lens().set_user_mat(source.get_mvp())
            uv = source.get_uv_region()
            self._display_regions[i].set_dimensions(uv.x, uv.x + uv.z, uv.y, uv.y + uv.w)

        self._queued_updates = []
Пример #24
0
    def update(self):
        for i in range(len(self._queued_updates), self._max_updates):
            self._cameras[i].set_active(False)
            self._display_regions[i].set_active(False)

        for i, source in enumerate(self._queued_updates):
            self._cameras[i].set_active(True)
            self._display_regions[i].set_active(True)
            self._cameras[i].get_lens().set_user_mat(source.get_mvp())
            uv = source.get_uv_region()
            self._display_regions[i].set_dimensions(uv.x, uv.x + uv.z, uv.y, uv.y + uv.w)

        self._queued_updates = []
Пример #25
0
 def _setup_textures(self):
     """ Prepares all bound textures """
     for i in range(self._aux_count):
         self._targets["aux_{}".format(i)] = Texture(
             self.debug_name + "_aux{}".format(i))
     for tex in itervalues(self._targets):
         tex.set_wrap_u(SamplerState.WM_clamp)
         tex.set_wrap_v(SamplerState.WM_clamp)
         tex.set_anisotropic_degree(0)
         tex.set_x_size(self._size.x)
         tex.set_y_size(self._size.y)
         tex.set_minfilter(SamplerState.FT_linear)
         tex.set_magfilter(SamplerState.FT_linear)
Пример #26
0
 def _setup_textures(self):
     """ Prepares all bound textures """
     for i in range(self._aux_count):
         self._targets["aux_{}".format(i)] = Texture(self.debug_name +
                                                     "_aux{}".format(i))
     for tex in itervalues(self._targets):
         tex.set_wrap_u(SamplerState.WM_clamp)
         tex.set_wrap_v(SamplerState.WM_clamp)
         tex.set_anisotropic_degree(0)
         tex.set_x_size(self._size.x)
         tex.set_y_size(self._size.y)
         tex.set_minfilter(SamplerState.FT_linear)
         tex.set_magfilter(SamplerState.FT_linear)
Пример #27
0
    def _create(self):
        """ Creates the internally used buffer """
        self._setup_textures()
        window_props, buffer_props = self._make_properties()

        self._internal_buffer = self.engine.make_output(
            self._source_window.get_pipe(), self.debug_name, 1, buffer_props,
            window_props,
            GraphicsPipe.BF_refuse_window | GraphicsPipe.BF_resizeable,
            self._source_window.gsg, self._source_window)

        if not self._internal_buffer:
            self.error("Failed to create buffer")
            return

        if self._depth_bits:
            self._internal_buffer.add_render_texture(
                self.depth_tex, GraphicsOutput.RTM_bind_or_copy,
                GraphicsOutput.RTP_depth)

        if max(self._color_bits) > 0:
            self._internal_buffer.add_render_texture(
                self.color_tex, GraphicsOutput.RTM_bind_or_copy,
                GraphicsOutput.RTP_color)

        aux_prefix = {
            8: "RTP_aux_rgba_{}",
            16: "RTP_aux_hrgba_{}",
            32: "RTP_aux_float_{}",
        }[self._aux_bits]

        for i in range(self._aux_count):
            target_mode = getattr(GraphicsOutput, aux_prefix.format(i))
            self._internal_buffer.add_render_texture(
                self.aux_tex[i], GraphicsOutput.RTM_bind_or_copy, target_mode)

        if not self.sort:
            RenderTarget.CURRENT_SORT += 20
            self.sort = RenderTarget.CURRENT_SORT

        RenderTarget.NUM_ALLOCATED_BUFFERS += 1
        self._internal_buffer.set_sort(self.sort)
        self._internal_buffer.disable_clears()
        self._internal_buffer.get_display_region(0).disable_clears()
        self._internal_buffer.get_overlay_display_region().disable_clears()
        self._internal_buffer.get_overlay_display_region().set_active(False)

        RenderTarget.REGISTERED_TARGETS.append(self)
        return True
Пример #28
0
    def _create(self):
        """ Creates the internally used buffer """
        self._setup_textures()
        window_props, buffer_props = self._make_properties()

        self._internal_buffer = self.engine.make_output(
            self._source_window.get_pipe(), self.debug_name, 1,
            buffer_props, window_props, GraphicsPipe.BF_refuse_window | GraphicsPipe.BF_resizeable,
            self._source_window.gsg, self._source_window)

        if not self._internal_buffer:
            self.error("Failed to create buffer")
            return

        if self._depth_bits:
            self._internal_buffer.add_render_texture(
                self.depth_tex, GraphicsOutput.RTM_bind_or_copy,
                GraphicsOutput.RTP_depth)

        if max(self._color_bits) > 0:
            self._internal_buffer.add_render_texture(
                self.color_tex, GraphicsOutput.RTM_bind_or_copy,
                GraphicsOutput.RTP_color)

        aux_prefix = {
            8: "RTP_aux_rgba_{}",
            16: "RTP_aux_hrgba_{}",
            32: "RTP_aux_float_{}",
        }[self._aux_bits]

        for i in range(self._aux_count):
            target_mode = getattr(GraphicsOutput, aux_prefix.format(i))
            self._internal_buffer.add_render_texture(
                self.aux_tex[i], GraphicsOutput.RTM_bind_or_copy, target_mode)

        if not self.sort:
            RenderTarget.CURRENT_SORT += 20
            self.sort = RenderTarget.CURRENT_SORT

        RenderTarget.NUM_ALLOCATED_BUFFERS += 1
        self._internal_buffer.set_sort(self.sort)
        self._internal_buffer.disable_clears()
        self._internal_buffer.get_display_region(0).disable_clears()
        self._internal_buffer.get_overlay_display_region().disable_clears()
        self._internal_buffer.get_overlay_display_region().set_active(False)

        RenderTarget.REGISTERED_TARGETS.append(self)
        return True
    def setup_shadows(self, light):
        light.init_shadow_sources()
        light.update_shadow_sources()

        num_sources = light.get_num_shadow_sources()
        base_slot = self._shadow_sources.find_consecutive_slots(num_sources)
        if base_slot < 0:
            print("ERROR: Failed to find slot for shadow sources!")
            return

        for i in range(num_sources):
            source = light.get_shadow_source(i)
            source.set_needs_update(True)
            slot = base_slot + i
            self._shadow_sources.reserve_slot(slot, source)
            source.set_slot(slot)
    def setup_shadows(self, light):
        light.init_shadow_sources()
        light.update_shadow_sources()

        num_sources = light.get_num_shadow_sources()
        base_slot = self._shadow_sources.find_consecutive_slots(num_sources)
        if base_slot < 0:
            print("ERROR: Failed to find slot for shadow sources!")
            return

        for i in range(num_sources):
            source = light.get_shadow_source(i)
            source.set_needs_update(True)
            slot = base_slot + i
            self._shadow_sources.reserve_slot(slot, source)
            source.set_slot(slot)
    def update(self):
        # First, disable all targets
        for target in itervalues(self._targets):
            target.active = False

        # Check for updated faces
        for i in range(6):
            if self._pipeline.task_scheduler.is_scheduled("envprobes_capture_envmap_face" + str(i)):
                self.regions[i].set_active(True)

        # Check for filtering
        if self._pipeline.task_scheduler.is_scheduled("envprobes_filter_and_store_envmap"):
            self.target_store.active = True
            self.target_store_diff.active = True
            self.filter_diffuse_target.active = True
            for target in self.filter_targets:
                target.active = True
Пример #32
0
    def update(self):
        # First, disable all targets
        for target in itervalues(self._targets):
            target.active = False

        # Check for updated faces
        for i in range(6):
            if self._pipeline.task_scheduler.is_scheduled("envprobes_capture_envmap_face" + str(i)):
                self.regions[i].set_active(True)

        # Check for filtering
        if self._pipeline.task_scheduler.is_scheduled("envprobes_filter_and_store_envmap"):
            self.target_store.active = True
            self.target_store_diff.active = True
            self.filter_diffuse_target.active = True
            for target in self.filter_targets:
                target.active = True
Пример #33
0
    def create(self):
        """ Creates the gui components """
        screen_w, screen_h = Globals.native_resolution.x, Globals.native_resolution.y
        self.fullscreen_node = Globals.base.pixel2dp.attach_new_node("LoadingScreen")
        self.fullscreen_node.set_bin("fixed", 10)
        self.fullscreen_node.set_depth_test(False)

        scale_w = screen_w / 1920.0
        scale_h = screen_h / 1080.0
        scale = max(scale_w, scale_h)

        self.fullscreen_bg = Sprite(
            image=self.image_source, x=(screen_w - 1920.0 * scale) // 2,
            y=(screen_h - 1080.0 * scale) // 2, w=int(1920 * scale),
            h=int(1080 * scale), parent=self.fullscreen_node, near_filter=False)

        for _ in range(2):
            Globals.base.graphicsEngine.render_frame()
Пример #34
0
    def create(self):
        """ Creates the gui components """
        screen_w, screen_h = Globals.base.win.get_x_size(), Globals.base.win.get_y_size()
        self.fullscreen_node = Globals.base.pixel2dp.attach_new_node("LoadingScreen")
        self.fullscreen_node.set_bin("fixed", 10)
        self.fullscreen_node.set_depth_test(False)

        scale_w = screen_w / 1920.0
        scale_h = screen_h / 1080.0
        scale = max(scale_w, scale_h)

        self.fullscreen_bg = Sprite(
            image="/$$rp/data/gui/loading_screen_bg.txo",
            x=(screen_w-1920.0*scale)//2, y=(screen_h-1080.0*scale)//2, w=int(1920 * scale),
            h=int(1080 * scale), parent=self.fullscreen_node, near_filter=False)

        for _ in range(2):
            Globals.base.graphicsEngine.render_frame()
    def on_pipeline_created(self):
        self.debug("Initializing pssm ..")
        # Construct a dummy node to parent the rig to
        self.node = Globals.base.render.attach_new_node("PSSMCameraRig")
        self.node.hide()

        # Construct the actual PSSM rig
        self.camera_rig = PSSMCameraRig(self.get_setting("split_count"))  # noqa # pylint: disable=undefined-variable
        self.camera_rig.set_sun_distance(self.get_setting("sun_distance"))
        self.camera_rig.set_pssm_distance(self.get_setting("max_distance"))
        self.camera_rig.set_logarithmic_factor(
            self.get_setting("logarithmic_factor"))
        self.camera_rig.set_border_bias(self.get_setting("border_bias"))
        self.camera_rig.set_use_stable_csm(True)
        self.camera_rig.set_use_fixed_film_size(True)
        self.camera_rig.set_resolution(self.get_setting("resolution"))
        self.camera_rig.reparent_to(self.node)

        # Attach the cameras to the shadow stage
        for i in range(self.get_setting("split_count")):
            camera_np = self.camera_rig.get_camera(i)
            camera_np.node().set_scene(Globals.base.render)
            region = self.shadow_stage.split_regions[i]
            region.set_camera(camera_np)
            # camera_np.node().show_frustum()

            # Make sure the pipeline knows about our camera, so it can apply
            # the correct bitmasks
            self._pipeline.tag_mgr.register_camera("shadow", camera_np.node())

        # Accept a shortcut to enable / disable the update of PSSM
        Globals.base.accept("u", self.toggle_update_enabled)

        # Set inputs
        self.pssm_stage.set_shader_inputs(
            pssm_mvps=self.camera_rig.get_mvp_array(),
            pssm_nearfar=self.camera_rig.get_nearfar_array())

        if self.is_plugin_enabled("volumetrics"):
            handle = self.get_plugin_instance("volumetrics")
            handle.stage.set_shader_inputs(
                pssm_mvps=self.camera_rig.get_mvp_array(),
                pssm_nearfar=self.camera_rig.get_nearfar_array())
Пример #36
0
 def create(self):
     current_tex = None
     self.blur_targets = []
     for i in range(3):
         target_h = self.create_target("BlurH-" + str(i))
         target_h.add_color_attachment(bits=16)
         target_h.prepare_buffer()
         target_h.set_shader_input("direction", LVecBase2i(1, 0))
         if current_tex is not None:
             target_h.set_shader_input("ShadedScene", current_tex, override=True)
         current_tex = target_h.color_tex
         target_v = self.create_target("BlurV-" + str(i))
         target_v.add_color_attachment(bits=16)
         target_v.prepare_buffer()
         target_v.set_shader_input("ShadedScene", current_tex, override=True)
         target_v.set_shader_input("direction", LVecBase2i(0, 1))
         current_tex = target_v.color_tex
         self.blur_targets += [target_h, target_v]
     self.final_tex = current_tex
Пример #37
0
    def on_pipeline_created(self):
        self.debug("Initializing pssm ..")
        # Construct a dummy node to parent the rig to
        self.node = Globals.base.render.attach_new_node("PSSMCameraRig")
        self.node.hide()

        # Construct the actual PSSM rig
        self.camera_rig = PSSMCameraRig(self.get_setting("split_count"))  # noqa # pylint: disable=undefined-variable
        self.camera_rig.set_sun_distance(self.get_setting("sun_distance"))
        self.camera_rig.set_pssm_distance(self.get_setting("max_distance"))
        self.camera_rig.set_logarithmic_factor(self.get_setting("logarithmic_factor"))
        self.camera_rig.set_border_bias(self.get_setting("border_bias"))
        self.camera_rig.set_use_stable_csm(True)
        self.camera_rig.set_use_fixed_film_size(True)
        self.camera_rig.set_resolution(self.get_setting("resolution"))
        self.camera_rig.reparent_to(self.node)

        # Attach the cameras to the shadow stage
        for i in range(self.get_setting("split_count")):
            camera_np = self.camera_rig.get_camera(i)
            camera_np.node().set_scene(Globals.base.render)
            region = self.shadow_stage.split_regions[i]
            region.set_camera(camera_np)
            # camera_np.node().show_frustum()

            # Make sure the pipeline knows about our camera, so it can apply
            # the correct bitmasks
            self._pipeline.tag_mgr.register_camera("shadow", camera_np.node())

        # Accept a shortcut to enable / disable the update of PSSM
        Globals.base.accept("u", self.toggle_update_enabled)

        # Set inputs
        self.pssm_stage.set_shader_inputs(
            pssm_mvps=self.camera_rig.get_mvp_array(),
            pssm_nearfar=self.camera_rig.get_nearfar_array())

        if self.is_plugin_enabled("volumetrics"):
            handle = self.get_plugin_instance("volumetrics")
            handle.stage.set_shader_inputs(
                pssm_mvps=self.camera_rig.get_mvp_array(),
                pssm_nearfar=self.camera_rig.get_nearfar_array())
Пример #38
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)
    def get_vertical_candela_value(self, horizontal_angle_idx, vertical_angle):
        if vertical_angle < 0.0:
            return 0.0

        if vertical_angle > self._vertical_angles[len(self._vertical_angles) - 1]:
            return 0.0

        for vertical_index in range(1, len(self._vertical_angles)):
            curr_angle = self._vertical_angles[vertical_index]

            if curr_angle > vertical_angle:
                prev_angle = self._vertical_angles[vertical_index - 1]
                prev_value = self.get_candela_value_from_index(
                    vertical_index - 1, horizontal_angle_idx)
                curr_value = self.get_candela_value_from_index(
                    vertical_index, horizontal_angle_idx)
                lerp = (vertical_angle - prev_angle) / (curr_angle - prev_angle)
                assert lerp >= 0.0 and lerp <= 1.0
                return curr_value * lerp + prev_value * (1.0 - lerp)
        return 0.0
Пример #40
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)
Пример #41
0
    def get_vertical_candela_value(self, horizontal_angle_idx, vertical_angle):
        if vertical_angle < 0.0:
            return 0.0

        if vertical_angle > self._vertical_angles[len(self._vertical_angles) - 1]:
            return 0.0

        for vertical_index in range(1, len(self._vertical_angles)):
            curr_angle = self._vertical_angles[vertical_index]

            if curr_angle > vertical_angle:
                prev_angle = self._vertical_angles[vertical_index - 1]
                prev_value = self.get_candela_value_from_index(
                    vertical_index - 1, horizontal_angle_idx)
                curr_value = self.get_candela_value_from_index(
                    vertical_index, horizontal_angle_idx)
                lerp = (vertical_angle - prev_angle) / (curr_angle - prev_angle)
                assert lerp >= 0.0 and lerp <= 1.0
                return curr_value * lerp + prev_value * (1.0 - lerp)
        return 0.0
    def create(self):
        """ Creates the gui components """
        screen_w, screen_h = Globals.native_resolution.x, Globals.native_resolution.y
        self.fullscreen_node = Globals.base.pixel2dp.attach_new_node(
            "LoadingScreen")
        self.fullscreen_node.set_bin("fixed", 10)
        self.fullscreen_node.set_depth_test(False)

        scale_w = screen_w / 1920.0
        scale_h = screen_h / 1080.0
        scale = max(scale_w, scale_h)

        self.fullscreen_bg = Sprite(image=self.image_source,
                                    x=(screen_w - 1920.0 * scale) // 2,
                                    y=(screen_h - 1080.0 * scale) // 2,
                                    w=int(1920 * scale),
                                    h=int(1080 * scale),
                                    parent=self.fullscreen_node,
                                    near_filter=False)

        for _ in range(2):
            Globals.base.graphicsEngine.render_frame()
Пример #43
0
 def create(self):
     current_tex = None
     self.blur_targets = []
     for i in range(3):
         target_h = self.create_target("BlurH-" + str(i))
         target_h.add_color_attachment(bits=16)
         target_h.prepare_buffer()
         target_h.set_shader_input("direction", LVecBase2i(1, 0))
         if current_tex is not None:
             target_h.set_shader_input("ShadedScene",
                                       current_tex,
                                       override=True)
         current_tex = target_h.color_tex
         target_v = self.create_target("BlurV-" + str(i))
         target_v.add_color_attachment(bits=16)
         target_v.prepare_buffer()
         target_v.set_shader_input("ShadedScene",
                                   current_tex,
                                   override=True)
         target_v.set_shader_input("direction", LVecBase2i(0, 1))
         current_tex = target_v.color_tex
         self.blur_targets += [target_h, target_v]
     self.final_tex = current_tex
Пример #44
0
    def _setup_camera_rig(self):
        """ Setups the cameras to render a cubemap """
        directions = (Vec3(1, 0, 0), Vec3(-1, 0, 0), Vec3(0, 1, 0),
                      Vec3(0, -1, 0), Vec3(0, 0, 1), Vec3(0, 0, -1))

        # Prepare the display regions
        for i in range(6):
            region = self.target.internal_buffer.make_display_region(
                i / 6, i / 6 + 1 / 6, 0, 1)
            region.set_sort(25 + i)
            region.set_active(True)
            region.disable_clears()

            # Set the correct clears
            region.set_clear_depth_active(True)
            region.set_clear_depth(1.0)
            region.set_clear_color_active(True)
            region.set_clear_color(Vec4(0))

            lens = PerspectiveLens()
            lens.set_fov(90)
            lens.set_near_far(0.001, 1.0)
            camera = Camera("EnvmapCam-" + str(i), lens)
            camera_np = self.rig_node.attach_new_node(camera)
            camera_np.look_at(camera_np, directions[i])
            region.set_camera(camera_np)
            self.regions.append(region)
            self.cameras.append(camera_np)

        self.cameras[0].set_r(90)
        self.cameras[1].set_r(-90)
        self.cameras[3].set_r(180)
        self.cameras[5].set_r(180)

        # Register cameras
        for camera_np in self.cameras:
            self._pipeline.tag_mgr.register_camera("envmap", camera_np.node())
    def remove_light(self, light):
        assert light is not None
        if not light.has_slot():
            print("ERROR: Could not detach light, light was not attached!")
            return

        self._lights.free_slot(light.get_slot())
        self.gpu_remove_light(light)
        light.remove_slot()

        if light.get_casts_shadows():

            for i in range(light.get_num_shadow_sources()):
                source = light.get_shadow_source(i)
                if source.has_slot():
                    self._shadow_sources.free_slot(source.get_slot())
                if source.has_region():
                    self._shadow_manager.get_atlas().free_region(source.get_region())
                    source.clear_region()

            self.gpu_remove_consecutive_sources(
                light.get_shadow_source(0), light.get_num_shadow_sources())

            light.clear_shadow_sources()
Пример #46
0
 def begin(self):
     for i in range(self._max_index + 1):
         if self._data[i]:
             yield self._data[i]
Пример #47
0
 def free_consecutive_slots(self, slot, num_consecutive):
     for i in range(num_consecutive):
         self.free_slot(slot + i)
    def compute(self):
        """ Precomputes the scattering """

        self.debug("Precomputing ...")
        exec_cshader = self.exec_compute_shader

        # Transmittance
        exec_cshader(self.shaders["transmittance"],
                     {"dest": self.textures["transmittance"]},
                     (self.trans_w, self.trans_h, 1))

        # Delta E
        exec_cshader(
            self.shaders["delta_e"], {
                "transmittanceSampler": self.textures["transmittance"],
                "dest": self.textures["delta_e"]
            }, (self.sky_w, self.sky_h, 1))

        # Delta S
        exec_cshader(
            self.shaders["delta_sm_sr"], {
                "transmittanceSampler": self.textures["transmittance"],
                "destDeltaSR": self.textures["delta_sr"],
                "destDeltaSM": self.textures["delta_sm"]
            }, (self.res_mu_s_nu, self.res_mu, self.res_r), (8, 8, 8))

        # Copy deltaE to irradiance texture
        exec_cshader(
            self.shaders["copy_irradiance"], {
                "k": 0.0,
                "deltaESampler": self.textures["delta_e"],
                "dest": self.textures["irradiance"]
            }, (self.sky_w, self.sky_h, 1))

        # Copy delta s into inscatter texture
        exec_cshader(
            self.shaders["copy_inscatter"], {
                "deltaSRSampler": self.textures["delta_sr"],
                "deltaSMSampler": self.textures["delta_sm"],
                "dest": self.textures["inscatter"]
            }, (self.res_mu_s_nu, self.res_mu, self.res_r), (8, 8, 8))

        for order in range(2, 5):
            first = order == 2

            # Delta J
            exec_cshader(
                self.shaders["delta_j"], {
                    "transmittanceSampler": self.textures["transmittance"],
                    "deltaSRSampler": self.textures["delta_sr"],
                    "deltaSMSampler": self.textures["delta_sm"],
                    "deltaESampler": self.textures["delta_e"],
                    "dest": self.textures["delta_j"],
                    "first": first
                }, (self.res_mu_s_nu, self.res_mu, self.res_r), (8, 8, 8))

            # Delta E
            exec_cshader(
                self.shaders["irradiance_n"], {
                    "transmittanceSampler": self.textures["transmittance"],
                    "deltaSRSampler": self.textures["delta_sr"],
                    "deltaSMSampler": self.textures["delta_sm"],
                    "dest": self.textures["delta_e"],
                    "first": first
                }, (self.sky_w, self.sky_h, 1))

            # Delta Sr
            exec_cshader(
                self.shaders["delta_sr"], {
                    "transmittanceSampler": self.textures["transmittance"],
                    "deltaJSampler": self.textures["delta_j"],
                    "dest": self.textures["delta_sr"],
                    "first": first
                }, (self.res_mu_s_nu, self.res_mu, self.res_r), (8, 8, 8))

            # Add delta E to irradiance
            exec_cshader(
                self.shaders["add_delta_e"], {
                    "deltaESampler": self.textures["delta_e"],
                    "dest": self.textures["irradiance"],
                }, (self.sky_w, self.sky_h, 1))

            # Add deltaSr to inscatter texture
            exec_cshader(
                self.shaders["add_delta_sr"], {
                    "deltaSSampler": self.textures["delta_sr"],
                    "dest": self.textures["inscatter"]
                }, (self.res_mu_s_nu, self.res_mu, self.res_r), (8, 8, 8))

        # Make stages available
        for stage in [self.handle.display_stage, self.handle.envmap_stage]:
            stage.set_shader_inputs(
                InscatterSampler=self.textures["inscatter"],
                transmittanceSampler=self.textures["transmittance"],
                IrradianceSampler=self.textures["irradiance"])
Пример #49
0
    def prepare_scene(self, scene):
        """ Prepares a given scene, by converting panda lights to render pipeline
        lights. This also converts all empties with names starting with 'ENVPROBE'
        to environment probes. Conversion of blender to render pipeline lights
        is done by scaling their intensity by 100 to match lumens.

        Additionally, this finds all materials with the 'TRANSPARENT' shading
        model, and sets the proper effects on them to ensure they are rendered
        properly.

        This method also returns a dictionary with handles to all created
        objects, that is lights, environment probes, and transparent objects.
        This can be used to store them and process them later on, or delete
        them when a newer scene is loaded."""
        lights = []
        for light in scene.find_all_matches("**/+PointLight"):
            light_node = light.node()
            rp_light = PointLight()
            rp_light.pos = light.get_pos(Globals.base.render)
            rp_light.radius = light_node.max_distance
            rp_light.energy = 20.0 * light_node.color.w
            rp_light.color = light_node.color.xyz
            rp_light.casts_shadows = light_node.shadow_caster
            rp_light.shadow_map_resolution = light_node.shadow_buffer_size.x
            rp_light.inner_radius = 0.4

            self.add_light(rp_light)
            light.remove_node()
            lights.append(rp_light)

        for light in scene.find_all_matches("**/+Spotlight"):
            light_node = light.node()
            rp_light = SpotLight()
            rp_light.pos = light.get_pos(Globals.base.render)
            rp_light.radius = light_node.max_distance
            rp_light.energy = 20.0 * light_node.color.w
            rp_light.color = light_node.color.xyz
            rp_light.casts_shadows = light_node.shadow_caster
            rp_light.shadow_map_resolution = light_node.shadow_buffer_size.x
            rp_light.fov = light_node.exponent / math.pi * 180.0
            lpoint = light.get_mat(Globals.base.render).xform_vec((0, 0, -1))
            rp_light.direction = lpoint
            self.add_light(rp_light)
            light.remove_node()
            lights.append(rp_light)

        envprobes = []
        for np in scene.find_all_matches("**/ENVPROBE*"):
            probe = self.add_environment_probe()
            probe.set_mat(np.get_mat())
            probe.border_smoothness = 0.0001
            probe.parallax_correction = True
            np.remove_node()
            envprobes.append(probe)

        tristrips_warning_emitted = False
        transparent_objects = []
        for geom_np in scene.find_all_matches("**/+GeomNode"):
            geom_node = geom_np.node()
            geom_count = geom_node.get_num_geoms()
            for i in range(geom_count):
                state = geom_node.get_geom_state(i)
                geom = geom_node.get_geom(i)

                needs_conversion = False
                for prim in geom.get_primitives():
                    if isinstance(prim, GeomTristrips):
                        needs_conversion = True
                        if not tristrips_warning_emitted:
                            self.warn(
                                "At least one GeomNode (",
                                geom_node.get_name(),
                                "and possible more..) contains tristrips.")
                            self.warn(
                                "Due to a NVIDIA Driver bug, we have to convert them to triangles now."
                            )
                            self.warn(
                                "Consider exporting your models with the Bam Exporter to avoid this."
                            )
                            tristrips_warning_emitted = True
                            break

                if needs_conversion:
                    geom_node.modify_geom(i).decompose_in_place()

                if not state.has_attrib(MaterialAttrib):
                    self.warn("Geom", geom_node,
                              "has no material! Please fix this.")
                    continue

                material = state.get_attrib(MaterialAttrib).get_material()
                shading_model = material.emission.x

                # SHADING_MODEL_TRANSPARENT
                if shading_model == 3:
                    if geom_count > 1:
                        self.error(
                            "Transparent materials must be on their own geom!\n"
                            "If you are exporting from blender, split them into\n"
                            "seperate meshes, then re-export your scene. The\n"
                            "problematic mesh is: " + geom_np.get_name())
                        continue
                    self.set_effect(geom_np, "/$$rp/effects/default.yaml", {
                        "render_forward": True,
                        "render_gbuffer": False
                    }, 100)

        return {
            "lights": lights,
            "envprobes": envprobes,
            "transparent_objects": transparent_objects
        }
Пример #50
0
 def free_region(self, region):
     self._num_used_tiles -= region.z * region.w
     for x in range(region.z):
         for y in range(region.w):
             self._flags[region.x + x][region.y + y] = False
Пример #51
0
 def region_is_free(self, x, y, w, h):
     for x_offset in range(w):
         for y_offset in range(h):
             if self._flags[x + x_offset][y + y_offset]:
                 return False
     return True
Пример #52
0
    def _load_and_parse_file(self, pth):
        """ Loads a .IES file from a given filename, returns an IESDataset
        which is used by the load function later on. """
        self.debug("Loading ies profile from", pth)

        try:
            with open(pth, "r") as handle:
                lines = handle.readlines()
        except IOError as msg:
            self.error("Failed to open", pth, ":", msg)
            return None

        lines = [i.strip() for i in lines]

        # Parse version header
        self._check_version_header(lines.pop(0))

        # Parse arbitrary amount of keywords
        keywords = self._extract_keywords(lines)  # noqa

        # Next line should be TILT=NONE according to the spec
        if lines.pop(0) != "TILT=NONE":
            raise InvalidIESProfileException("Expected TILT=NONE line, but none found!")

        # From now on, lines do not matter anymore, instead everything is
        # space seperated
        new_parts = (' '.join(lines)).replace(",", " ").split()

        def read_int():
            return int(new_parts.pop(0))

        def read_float():
            return float(new_parts.pop(0))

        # Amount of Lamps
        if read_int() != 1:
            raise InvalidIESProfileException("Only 1 Lamp supported!")

        # Extract various properties
        lumen_per_lamp = read_float()  # noqa
        candela_multiplier = read_float()  # noqa
        num_vertical_angles = read_int()
        num_horizontal_angles = read_int()

        if num_vertical_angles < 1 or num_horizontal_angles < 1:
            raise InvalidIESProfileException("Invalid of vertical/horizontal angles!")

        photometric_type = read_int()  # noqa
        unit_type = read_int()

        # Check for a correct unit type, should be 1 for meters and 2 for feet
        if unit_type not in [1, 2]:
            raise InvalidIESProfileException("Invalid unit type")

        width = read_float()  # noqa
        length = read_float()  # noqa
        height = read_float()  # noqa
        ballast_factor = read_float()  # noqa
        future_use = read_float()  # Unused field for future usage  # noqa
        input_watts = read_float()  # noqa

        # Read vertical angles
        vertical_angles = [read_float() for i in range(num_vertical_angles)]
        horizontal_angles = [read_float() for i in range(num_horizontal_angles)]

        candela_values = []
        candela_scale = 0.0

        for i in range(num_horizontal_angles):
            vertical_data = [read_float() for i in range(num_vertical_angles)]
            candela_scale = max(candela_scale, max(vertical_data))
            candela_values += vertical_data

        # Rescale values, divide by maximum
        candela_values = [i / candela_scale for i in candela_values]

        if len(new_parts) != 0:
            self.warn("Unhandled data at file-end left:", new_parts)

            # Dont abort here, some formats like those from ERCO Leuchten GmbH
            # have an END keyword, just ignore everything after the data was
            # read in.

        dataset = IESDataset()
        dataset.set_vertical_angles(self._list_to_pta(vertical_angles))
        dataset.set_horizontal_angles(self._list_to_pta(horizontal_angles))
        dataset.set_candela_values(self._list_to_pta(candela_values))

        # Testing code to write out the LUT
        # from panda3d.core import Texture
        # tex = Texture("temp")
        # tex.setup_3d_texture(512, 512, 1, Image.T_float, Image.F_r16)
        # dataset.generate_dataset_texture_into(tex, 0)
        # tex.write("generated.png")

        return dataset
Пример #53
0
    def _draw(self, painter):
        """ Internal method to draw the widget """

        canvas_width = self.width() - self._legend_border
        canvas_height = self.height() - self._legend_border - self._bar_h

        # Draw field background
        # painter.setPen(QtGui.QColor(200, 200, 200))
        # painter.setBrush(QtGui.QColor(230, 230, 230))
        # painter.drawRect(0, 0, self.width() - 1, self.height() - 1)

        # Draw legend

        # Compute amount of horizontal / vertical lines
        num_vert_lines = 12  # 24 / 12 = 2, one entry per 2 hours
        line_spacing_x = (self.width() - self._legend_border) / num_vert_lines
        line_spacing_y = (self.height() - self._legend_border -
                          self._bar_h) / 20.0
        num_horiz_lines = int(
            math.ceil(canvas_height / float(line_spacing_y)) + 1)

        # Draw vertical lines
        painter.setPen(QtGui.QColor(200, 200, 200))
        for i in range(num_vert_lines + 1):
            line_pos = i * line_spacing_x + self._legend_border - 1
            painter.drawLine(line_pos, self._bar_h, line_pos,
                             canvas_height + self._bar_h)

        # Draw horizontal lines
        painter.setPen(QtGui.QColor(200, 200, 200))
        for i in range(num_horiz_lines):
            line_pos = canvas_height - i * line_spacing_y + self._bar_h
            painter.drawLine(self._legend_border, line_pos, self.width(),
                             line_pos)

        # Draw vetical legend labels
        painter.setPen(QtGui.QColor(120, 120, 120))
        for i in range(num_horiz_lines):
            line_pos = canvas_height - i * line_spacing_y + self._bar_h
            # painter.drawText(6, line_pos + 3, str(round(float(i) / (num_horiz_lines-1), 2)))
            painter.drawText(
                6, line_pos + 3,
                self._unit_processor(float(i) / (num_horiz_lines - 1)))

        # Draw horizontal legend labels
        for i in range(num_vert_lines + 1):
            line_pos = i * line_spacing_x + self._legend_border
            offpos_x = -14
            if i == 0:
                offpos_x = -2
            elif i == num_vert_lines:
                offpos_x = -27
            time_string = str(int(
                float(i) / num_vert_lines * 24)).zfill(2) + ":00"
            painter.drawText(line_pos + offpos_x,
                             canvas_height + self._bar_h + 18, time_string)

        # Draw curve
        for index, curve in enumerate(self._curves):
            painter.setPen(QtGui.QColor(*curve.color))
            last_value = 0
            for i in range(canvas_width):
                rel_offset = i / (canvas_width - 1.0)
                curve_height = self._get_y_value_for(
                    curve.get_value(rel_offset))

                if i == 0:
                    last_value = curve_height

                painter.drawLine(self._legend_border + i - 1, last_value,
                                 self._legend_border + i, curve_height)
                last_value = curve_height

            # Draw the CV points of the curve
            painter.setBrush(QtGui.QColor(240, 240, 240))

            for cv_index, (x, y) in enumerate(curve.control_points):
                offs_x = x * canvas_width + self._legend_border
                offs_y = (1 - y) * canvas_height + self._bar_h

                if (self._selected_point and self._selected_point[0] == index
                        and self._selected_point[1] == cv_index):
                    painter.setPen(QtGui.QColor(255, 0, 0))
                else:
                    painter.setPen(QtGui.QColor(100, 100, 100))
                painter.drawRect(offs_x - self._cv_point_size,
                                 offs_y - self._cv_point_size,
                                 2 * self._cv_point_size,
                                 2 * self._cv_point_size)

        # Draw bar background
        bar_half_height = 4
        bar_top_pos = 10

        painter.setBrush(QtGui.QColor(255, 0, 0))
        painter.setPen(QtGui.QColor(110, 110, 110))

        painter.drawRect(self._legend_border - 1, bar_top_pos - 1,
                         self.width() - self._legend_border,
                         2 * bar_half_height + 2)

        # Draw bar
        if len(self._curves) == 0:
            return

        if len(self._curves) == 1:
            bar_curve = self._curves[0]
        else:
            bar_curve = self._curves[0:3]

        for i in range(canvas_width - 1):
            xpos = self._legend_border + i
            relv = float(i) / float(canvas_width)

            if len(self._curves) == 1:
                val = max(0, min(255, int(bar_curve.get_value(relv) * 255.0)))
                painter.setPen(QtGui.QColor(val, val, val))
            else:
                r = max(0, min(255, int(bar_curve[0].get_value(relv) * 255.0)))
                g = max(0, min(255, int(bar_curve[1].get_value(relv) * 255.0)))
                b = max(0, min(255, int(bar_curve[2].get_value(relv) * 255.0)))
                painter.setPen(QtGui.QColor(r, g, b))
            painter.drawLine(xpos, bar_top_pos, xpos,
                             bar_top_pos + 2 * bar_half_height)

        # Draw selected time
        if self._drag_point:
            painter.setBrush(QtGui.QColor(200, 200, 200))
            painter.setPen(QtGui.QColor(90, 90, 90))
            offs_x = max(
                0,
                min(canvas_width + 10,
                    self._drag_time * canvas_width + self._legend_border - 19))
            offs_y = self.height() - self._legend_border
            minutes = int(self._drag_time * 24 * 60)
            hours = minutes / 60
            minutes = minutes % 60
            painter.drawRect(offs_x,
                             self.height() - self._legend_border + 5, 40, 20)
            painter.drawText(offs_x + 7, offs_y + 20,
                             "{:02}:{:02}".format(hours, minutes))

            painter.setPen(QtGui.QColor(150, 150, 150))
            painter.drawLine(offs_x + 19, bar_top_pos + 15, offs_x + 19,
                             self.height() - self._legend_border + 5)

        # Display current time
        pen = QtGui.QPen()
        pen.setColor(QtGui.QColor(255, 100, 100))
        pen.setStyle(QtCore.Qt.DashLine)
        painter.setPen(pen)

        xoffs = self._legend_border + self._current_time * (canvas_width - 1)
        painter.drawLine(xoffs, self._bar_h, xoffs,
                         self._bar_h + canvas_height)

        # Draw usage hints
        painter.setPen(QtGui.QColor(100, 100, 100))
        painter.drawText(
            5,
            self.height() - 2,
            "Click on the curve to add new control points, click and drag "
            "existing points to move them.")
Пример #54
0
    def prepare_scene(self, scene):
        """ Prepares a given scene, by converting panda lights to render pipeline
        lights """

        # TODO: IES profiles
        ies_profile = self.load_ies_profile("soft_display.ies") # pylint: disable=W0612
        lights = []

        for light in scene.find_all_matches("**/+PointLight"):
            light_node = light.node()
            rp_light = PointLight()
            rp_light.pos = light.get_pos(Globals.base.render)
            rp_light.radius = light_node.max_distance
            rp_light.energy = 100.0 * light_node.color.w
            rp_light.color = light_node.color.xyz
            rp_light.casts_shadows = light_node.shadow_caster
            rp_light.shadow_map_resolution = light_node.shadow_buffer_size.x
            rp_light.inner_radius = 0.8
            self.add_light(rp_light)
            light.remove_node()
            lights.append(rp_light)

        for light in scene.find_all_matches("**/+Spotlight"):
            light_node = light.node()
            rp_light = SpotLight()
            rp_light.pos = light.get_pos(Globals.base.render)
            rp_light.radius = light_node.max_distance
            rp_light.energy = 100.0 * light_node.color.w
            rp_light.color = light_node.color.xyz
            rp_light.casts_shadows = light_node.shadow_caster
            rp_light.shadow_map_resolution = light_node.shadow_buffer_size.x
            rp_light.fov = light_node.exponent / math.pi * 180.0
            lpoint = light.get_mat(Globals.base.render).xform_vec((0, 0, -1))
            rp_light.direction = lpoint
            self.add_light(rp_light)
            light.remove_node()
            lights.append(rp_light)

        envprobes = []

        # Add environment probes
        for np in scene.find_all_matches("**/ENVPROBE*"):
            probe = self.add_environment_probe()
            probe.set_mat(np.get_mat())
            probe.border_smoothness = 0.001
            probe.parallax_correction = True
            np.remove_node()
            envprobes.append(probe)

        # Find transparent objects and set the right effect
        for geom_np in scene.find_all_matches("**/+GeomNode"):
            geom_node = geom_np.node()
            geom_count = geom_node.get_num_geoms()
            for i in range(geom_count):
                state = geom_node.get_geom_state(i)
                if not state.has_attrib(MaterialAttrib):
                    self.warn("Geom", geom_node, "has no material!")
                    continue
                material = state.get_attrib(MaterialAttrib).get_material()
                shading_model = material.emission.x

                # SHADING_MODEL_TRANSPARENT
                if shading_model == 3:
                    if geom_count > 1:
                        self.error("Transparent materials must have their own geom!")
                        continue

                    self.set_effect(
                        geom_np, "effects/default.yaml",
                        {"render_forward": True, "render_gbuffer": False}, 100)

                 # SHADING_MODEL_FOLIAGE
                elif shading_model == 5:
                    # XXX: Maybe only enable alpha testing for foliage unless
                    # specified otherwise
                    pass


        return {"lights": lights, "envprobes": envprobes}
Пример #55
0
    def _draw(self, painter):
        """ Internal method to draw the widget """

        canvas_width = self.width() - self._legend_border
        canvas_height = self.height() - self._legend_border - self._bar_h

        # Draw field background
        # painter.setPen(QtGui.QColor(200, 200, 200))
        # painter.setBrush(QtGui.QColor(230, 230, 230))
        # painter.drawRect(0, 0, self.width() - 1, self.height() - 1)

        # Draw legend

        # Compute amount of horizontal / vertical lines
        num_vert_lines = 12 # 24 / 12 = 2, one entry per 2 hours
        line_spacing_x = (self.width() - self._legend_border) / num_vert_lines
        line_spacing_y = (self.height() - self._legend_border - self._bar_h) / 20.0
        num_horiz_lines = int(math.ceil(canvas_height / float(line_spacing_y)) + 1)

        # Draw vertical lines
        painter.setPen(QtGui.QColor(200, 200, 200))
        for i in range(num_vert_lines + 1):
            line_pos = i*line_spacing_x + self._legend_border - 1
            painter.drawLine(line_pos, self._bar_h, line_pos, canvas_height + self._bar_h)

        # Draw horizontal lines
        painter.setPen(QtGui.QColor(200, 200, 200))
        for i in range(num_horiz_lines):
            line_pos = canvas_height - i*line_spacing_y + self._bar_h
            painter.drawLine(self._legend_border, line_pos, self.width(), line_pos)

        # Draw vetical legend labels
        painter.setPen(QtGui.QColor(120, 120, 120))
        for i in range(num_horiz_lines):
            line_pos = canvas_height - i*line_spacing_y + self._bar_h
            # painter.drawText(6, line_pos + 3, str(round(float(i) / (num_horiz_lines-1), 2)))
            painter.drawText(6, line_pos + 3, self._unit_processor(float(i) / (num_horiz_lines-1)))

        # Draw horizontal legend labels
        for i in range(num_vert_lines + 1):
            line_pos = i*line_spacing_x + self._legend_border
            offpos_x = -14
            if i == 0:
                offpos_x = -2
            elif i == num_vert_lines:
                offpos_x = -27
            time_string = str(int(float(i) / num_vert_lines * 24)).zfill(2) + ":00"
            painter.drawText(line_pos + offpos_x, canvas_height + self._bar_h + 18, time_string)

        # Draw curve
        for index, curve in enumerate(self._curves):
            painter.setPen(QtGui.QColor(*curve.color))
            last_value = 0
            for i in range(canvas_width):
                rel_offset = i / (canvas_width - 1.0)
                curve_height = self._get_y_value_for(curve.get_value(rel_offset))

                if i == 0:
                    last_value = curve_height

                painter.drawLine(self._legend_border + i-1, last_value, self._legend_border + i, curve_height)
                last_value = curve_height

            # Draw the CV points of the curve
            painter.setBrush(QtGui.QColor(240, 240, 240))

            for cv_index, (x, y) in enumerate(curve.control_points):
                offs_x = x * canvas_width + self._legend_border
                offs_y = (1-y) * canvas_height + self._bar_h

                if self._selected_point and self._selected_point[0] == index and self._selected_point[1] == cv_index:
                    painter.setPen(QtGui.QColor(255, 0, 0))
                else:
                    painter.setPen(QtGui.QColor(100, 100, 100))
                painter.drawRect(offs_x - self._cv_point_size, offs_y - self._cv_point_size,
                    2*self._cv_point_size, 2*self._cv_point_size)


        # Draw bar background
        bar_half_height = 4
        bar_top_pos = 10

        painter.setBrush(QtGui.QColor(255, 0, 0))
        painter.setPen(QtGui.QColor(110, 110, 110))

        painter.drawRect(self._legend_border - 1, bar_top_pos - 1, self.width() - self._legend_border, 2*bar_half_height + 2)

        # Draw bar
        if len(self._curves) == 0:
            return

        if len(self._curves) == 1:
            bar_curve = self._curves[0]
        else:
            bar_curve = self._curves[0:3]

        for i in range(canvas_width - 1):
            xpos = self._legend_border + i
            relv = float(i) / float(canvas_width)

            if len(self._curves) == 1:
                val = max(0, min(255, int(bar_curve.get_value(relv) * 255.0)))
                painter.setPen(QtGui.QColor(val, val, val))
            else:
                r = max(0, min(255, int(bar_curve[0].get_value(relv) * 255.0)))
                g = max(0, min(255, int(bar_curve[1].get_value(relv) * 255.0)))
                b = max(0, min(255, int(bar_curve[2].get_value(relv) * 255.0)))
                painter.setPen(QtGui.QColor(r, g, b))
            painter.drawLine(xpos, bar_top_pos, xpos, bar_top_pos + 2 * bar_half_height)

        # Draw selected time
        if self._drag_point:
            painter.setBrush(QtGui.QColor(200, 200, 200))
            painter.setPen(QtGui.QColor(90, 90, 90))
            offs_x = max(0, min(canvas_width + 10, self._drag_time * canvas_width + self._legend_border - 19))
            offs_y = self.height() - self._legend_border
            minutes = int(self._drag_time * 24 * 60)
            hours = minutes / 60
            minutes = minutes % 60
            painter.drawRect(offs_x, self.height() - self._legend_border + 5, 40, 20)
            painter.drawText(offs_x + 7, offs_y + 20, "{:02}:{:02}".format(hours, minutes))

            painter.setPen(QtGui.QColor(150, 150, 150))
            painter.drawLine(offs_x + 19, bar_top_pos + 15, offs_x + 19, self.height() - self._legend_border + 5)

        # Display current time
        pen = QtGui.QPen()
        pen.setColor(QtGui.QColor(255, 100, 100))
        pen.setStyle(QtCore.Qt.DashLine)
        painter.setPen(pen)

        xoffs = self._legend_border + self._current_time * (canvas_width-1)
        painter.drawLine(xoffs, self._bar_h, xoffs, self._bar_h + canvas_height)

        # Draw usage hints
        painter.setPen(QtGui.QColor(100, 100, 100))
        painter.drawText(5, self.height() - 2, "Click on the curve to add new control points, click and drag existing points to move them.")
Пример #56
0
    def _load_and_parse_file(self, pth):
        """ Loads a .IES file from a given filename, returns an IESDataset
        which is used by the load function later on. """
        self.debug("Loading ies profile from", pth)

        try:
            with open(pth, "r") as handle:
                lines = handle.readlines()
        except IOError as msg:
            self.error("Failed to open", pth, ":", msg)
            return None

        lines = [i.strip() for i in lines]

        # Parse version header
        self._check_version_header(lines.pop(0))

        # Parse arbitrary amount of keywords
        keywords = self._extract_keywords(lines)

        # Next line should be TILT=NONE according to the spec
        if lines.pop(0) != "TILT=NONE":
            raise InvalidIESProfileException("Expected TILT=NONE line, but none found!")

        # From now on, lines do not matter anymore, instead everything is
        # space seperated
        new_parts = (' '.join(lines)).replace(",", " ").split()
        read_int = lambda: int(new_parts.pop(0))
        read_float = lambda: float(new_parts.pop(0))

        # Amount of Lamps
        if read_int() != 1:
            raise InvalidIESProfileException("Only 1 Lamp supported!")

        # Extract various properties
        lumen_per_lamp = read_float()
        candela_multiplier = read_float()
        num_vertical_angles = read_int()
        num_horizontal_angles = read_int()

        if num_vertical_angles < 1 or num_horizontal_angles < 1:
            raise InvalidIESProfileException("Invalid of vertical/horizontal angles!")

        photometric_type = read_int()
        unit_type = read_int()

        # Check for a correct unit type, should be 1 for meters and 2 for feet
        if unit_type not in [1, 2]:
            raise InvalidIESProfileException("Invalid unit type")

        width = read_float()
        length = read_float()
        height = read_float()
        ballast_factor = read_float()
        future_use = read_float() # Unused field for future usage
        input_watts = read_float()

        # Read vertical angles
        vertical_angles = [read_float() for i in range(num_vertical_angles)]
        horizontal_angles = [read_float() for i in range(num_horizontal_angles)]

        candela_values = []
        candela_scale = 0.0

        for i in range(num_horizontal_angles):
            vertical_data = [read_float() for i in range(num_vertical_angles)]
            candela_scale = max(candela_scale, max(vertical_data))
            candela_values += vertical_data

        # Rescale values, divide by maximum
        candela_values = [i / candela_scale for i in candela_values]

        if len(new_parts) != 0:
            self.warn("Unhandled data at file-end left:", new_parts)

            # Dont abort here, some formats like those from ERCO Leuchten GmbH
            # have an END keyword, just ignore everything after the data was
            # read in.

        dataset = IESDataset()
        dataset.set_vertical_angles(self._list_to_pta(vertical_angles))
        dataset.set_horizontal_angles(self._list_to_pta(horizontal_angles))
        dataset.set_candela_values(self._list_to_pta(candela_values))

        # Testing code to write out the LUT
        # from panda3d.core import Texture
        # tex = Texture("temp")
        # tex.setup_3d_texture(512, 512, 1, Image.T_float, Image.F_r16)
        # dataset.generate_dataset_texture_into(tex, 0)
        # tex.write("generated.png")

        return dataset
Пример #57
0
 def region_is_free(self, x, y, w, h):
     for x_offset in range(w):
         for y_offset in range(h):
             if self._flags[x + x_offset][y + y_offset]:
                 return False
     return True
Пример #58
0
 def free_region(self, region):
     self._num_used_tiles -= region.z * region.w
     for x in range(region.z):
         for y in range(region.w):
             self._flags[region.x + x][region.y + y] = False