class WindowEvents(mglw.WindowConfig):
    gl_version = (3, 3)
    title = "imgui Integration"
    resource_dir = (Path(__file__).parent / 'resources').resolve()
    aspect_ratio = None

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        imgui.create_context()
        self.wnd.ctx.error
        self.imgui = ModernglWindowRenderer(self.wnd)

        self.cube = geometry.cube(size=(2, 2, 2))
        self.prog = self.load_program('programs/cube_simple.glsl')
        self.prog['color'].value = (1.0, 1.0, 1.0, 1.0)
        self.prog['m_camera'].write(Matrix44.identity(dtype='f4'))
        self.prog['m_proj'].write(
            Matrix44.perspective_projection(75,
                                            self.wnd.aspect_ratio,
                                            1,
                                            100,
                                            dtype='f4'))

    def render(self, time: float, frametime: float):
        rotation = Matrix44.from_eulers((time, time, time), dtype='f4')
        translation = Matrix44.from_translation((0.0, 0.0, -3.5), dtype='f4')
        model = translation * rotation

        self.ctx.enable(moderngl.DEPTH_TEST | moderngl.CULL_FACE)
        self.prog['m_model'].write(model)
        self.cube.render(self.prog)

        self.render_ui()

    def render_ui(self):
        imgui.new_frame()
        if imgui.begin_main_menu_bar():
            if imgui.begin_menu("File", True):

                clicked_quit, selected_quit = imgui.menu_item(
                    "Quit", 'Cmd+Q', False, True)

                if clicked_quit:
                    exit(1)

                imgui.end_menu()
            imgui.end_main_menu_bar()

        imgui.show_test_window()

        imgui.begin("Custom window", True)
        imgui.text("Bar")
        imgui.text_colored("Eggs", 0.2, 1., 0.)
        imgui.end()

        imgui.render()
        self.imgui.render(imgui.get_draw_data())

    def resize(self, width: int, height: int):
        self.prog['m_proj'].write(
            Matrix44.perspective_projection(75,
                                            self.wnd.aspect_ratio,
                                            1,
                                            100,
                                            dtype='f4'))
        self.imgui.resize(width, height)

    def key_event(self, key, action, modifiers):
        self.imgui.key_event(key, action, modifiers)

    def mouse_position_event(self, x, y, dx, dy):
        self.imgui.mouse_position_event(x, y, dx, dy)

    def mouse_drag_event(self, x, y, dx, dy):
        self.imgui.mouse_drag_event(x, y, dx, dy)

    def mouse_scroll_event(self, x_offset, y_offset):
        self.imgui.mouse_scroll_event(x_offset, y_offset)

    def mouse_press_event(self, x, y, button):
        self.imgui.mouse_press_event(x, y, button)

    def mouse_release_event(self, x: int, y: int, button: int):
        self.imgui.mouse_release_event(x, y, button)

    def unicode_char_entered(self, char):
        self.imgui.unicode_char_entered(char)
Example #2
0
class SlimeWindow(mglw.WindowConfig):
    title = "Slimes"
    gl_version = (4, 5)
    window_size = (1280, 720)
    resource_dir = (pathlib.Path(__file__).parent / "resources").resolve()
    map_size = (2560, 1440)
    local_size = 1024
    vsync = True

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        imgui.create_context()
        self.wnd.ctx.error
        self.imgui = ModernglWindowRenderer(self.wnd)

        self.world_texture01 = self.ctx.texture(self.map_size, 1, dtype="f1")
        self.world_texture01.repeat_x, self.world_texture01.repeat_y = False, False
        self.world_texture01.filter = mgl.NEAREST, mgl.NEAREST

        self.world_texture02 = self.ctx.texture(self.map_size, 1, dtype="f1")
        self.world_texture02.repeat_x, self.world_texture02.repeat_y = False, False
        self.world_texture02.filter = mgl.NEAREST, mgl.NEAREST

        data = gen_data(SlimeConfig.N, self.map_size).astype("f4")
        self.slimes = self.ctx.buffer(data)  # each slime has a position and angle

        self.load_programs()

        self.update_uniforms()

        self.quad_fs = quad_fs(normals=False)

    def restart_sim(self):
        self.world_texture01.release()
        self.world_texture02.release()

        self.world_texture01 = self.ctx.texture(self.map_size, 1, dtype="f1")
        self.world_texture01.repeat_x, self.world_texture01.repeat_y = False, False
        self.world_texture01.filter = mgl.NEAREST, mgl.NEAREST

        self.world_texture02 = self.ctx.texture(self.map_size, 1, dtype="f1")
        self.world_texture02.repeat_x, self.world_texture02.repeat_y = False, False
        self.world_texture02.filter = mgl.NEAREST, mgl.NEAREST

        data = gen_data(SlimeConfig.N, self.map_size).astype("f4")
        self.slimes.orphan(SlimeConfig.N * 4 * 4)
        self.slimes.write(data)

    def update_uniforms(self):
        self.blurr["diffuseSpeed"] = SlimeConfig.diffusion_speed
        self.blurr["evaporateSpeed"] = SlimeConfig.evaporation_speed

        self.compute_shader["moveSpeed"] = SlimeConfig.move_speed
        self.compute_shader["turnSpeed"] = SlimeConfig.turn_speed

        self.compute_shader["senorAngleSpacing"] = SlimeConfig.sensor_angle
        self.compute_shader["sensorDst"] = SlimeConfig.sensor_distance
        self.compute_shader["sensorSize"] = SlimeConfig.sensor_size

        self.render_program["color1"] = SlimeConfig.color1
        self.render_program["color2"] = SlimeConfig.color2

        self.compute_shader["N"] = SlimeConfig.N

    def load_programs(self):
        self.render_program = self.load_program("render_texture.glsl")
        self.render_program["texture0"] = 0
        self.compute_shader = self.load_compute_shader(
            "update.glsl",
            {
                "width": self.map_size[0],
                "height": self.map_size[1],
                "local_size": self.local_size,
            },
        )
        self.blurr = self.load_compute_shader("blur.glsl")

    def render(self, time: float, frame_time: float):
        self.world_texture01.use(0)
        self.quad_fs.render(self.render_program)

        self.world_texture01.bind_to_image(1, read=True, write=False)
        self.world_texture02.bind_to_image(0, read=False, write=True)
        self.slimes.bind_to_storage_buffer(2)

        self.compute_shader["dt"] = frame_time
        self.blurr["dt"] = frame_time

        group_size = int(math.ceil(SlimeConfig.N / self.local_size))
        self.compute_shader.run(group_size, 1, 1)

        self.world_texture01.bind_to_image(0, read=True, write=False)
        self.world_texture02.bind_to_image(1, read=True, write=True)
        self.blurr.run(self.map_size[0] // 16 + 1, self.map_size[1] // 16 + 1)

        self.world_texture01, self.world_texture02 = (
            self.world_texture02,
            self.world_texture01,
        )

        self.render_ui()

    def render_ui(self):
        imgui.new_frame()
        if imgui.begin("Settings"):
            imgui.push_item_width(imgui.get_window_width() * 0.33)
            changed = False
            c, SlimeConfig.move_speed = imgui.slider_float(
                "Movement speed", SlimeConfig.move_speed, 0.5, 50
            )
            changed = changed or c
            c, SlimeConfig.turn_speed = imgui.slider_float(
                "Turn speed",
                SlimeConfig.turn_speed,
                0.5,
                50,
            )
            changed = changed or c
            c, SlimeConfig.evaporation_speed = imgui.slider_float(
                "Evaporation speed", SlimeConfig.evaporation_speed, 0.1, 10
            )
            changed = changed or c
            c, SlimeConfig.diffusion_speed = imgui.slider_float(
                "Diffusion speed",
                SlimeConfig.diffusion_speed,
                0.1,
                10,
            )
            changed = changed or c
            c, SlimeConfig.sensor_angle = imgui.slider_float(
                "Sensor-angle",
                SlimeConfig.sensor_angle,
                0,
                np.pi,
            )
            changed = changed or c
            c, SlimeConfig.sensor_size = imgui.slider_int(
                "Sensor-size",
                SlimeConfig.sensor_size,
                1,
                3,
            )
            changed = changed or c
            c, SlimeConfig.sensor_distance = imgui.slider_int(
                "Sensor distance",
                SlimeConfig.sensor_distance,
                1,
                10,
            )
            changed = changed or c
            if changed:
                self.update_uniforms()
            imgui.pop_item_width()

        imgui.end()

        if imgui.begin("Appearance"):
            imgui.push_item_width(imgui.get_window_width() * 0.33)
            changed_c1, SlimeConfig.color1 = imgui.color_edit3(
                "Color1", *SlimeConfig.color1
            )
            changed_c2, SlimeConfig.color2 = imgui.color_edit3(
                "Color2", *SlimeConfig.color2
            )
            if changed_c1 or changed_c2:
                self.update_uniforms()

        imgui.end()

        if imgui.begin("Actions"):
            imgui.push_item_width(imgui.get_window_width() * 0.33)
            changed, SlimeConfig.N = imgui.input_int(
                "Number of Slimes", SlimeConfig.N, step=1024, step_fast=2**15
            )
            SlimeConfig.N = min(max(2048, SlimeConfig.N), 2**24)
            if imgui.button("Restart Slimes"):
                self.restart_sim()

            imgui.pop_item_width()

        imgui.end()
        imgui.render()
        self.imgui.render(imgui.get_draw_data())

    def resize(self, width: int, height: int):
        self.imgui.resize(width, height)

    def key_event(self, key, action, modifiers):
        self.imgui.key_event(key, action, modifiers)

    def mouse_position_event(self, x, y, dx, dy):
        self.imgui.mouse_position_event(x, y, dx, dy)

    def mouse_drag_event(self, x, y, dx, dy):
        self.imgui.mouse_drag_event(x, y, dx, dy)

    def mouse_scroll_event(self, x_offset, y_offset):
        self.imgui.mouse_scroll_event(x_offset, y_offset)

    def mouse_press_event(self, x, y, button):
        self.imgui.mouse_press_event(x, y, button)

    def mouse_release_event(self, x: int, y: int, button: int):
        self.imgui.mouse_release_event(x, y, button)

    def unicode_char_entered(self, char):
        self.imgui.unicode_char_entered(char)
Example #3
0
class WindowEvents(mglw.WindowConfig):
    gl_version = (3, 3)
    title = "imgui Integration"
    resource_dir = (Path(__file__).parent / '../examples/resources').resolve()
    aspect_ratio = None

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        imgui.create_context()
        self.wnd.ctx.error
        self.imgui = ModernglWindowRenderer(self.wnd)

        self.cube = geometry.cube(size=(2, 2, 2))
        self.prog = self.load_program('programs/cube_simple.glsl')
        self.prog['color'].value = (1.0, 1.0, 1.0, 1.0)
        self.prog['m_camera'].write(Matrix44.identity(dtype='f4'))
        self.prog['m_proj'].write(
            Matrix44.perspective_projection(75, 1.0, 1, 100, dtype='f4'))

        self.fbo = self.ctx.framebuffer(
            color_attachments=self.ctx.texture((512, 512), 4),
            depth_attachment=self.ctx.depth_texture((512, 512)),
        )
        # Ensure imgui knows about this texture
        # This is the color layer in the framebuffer
        self.imgui.register_texture(self.fbo.color_attachments[0])

    def render(self, time: float, frametime: float):
        # Rotate/move cube
        rotation = Matrix44.from_eulers((time, time, time), dtype='f4')
        translation = Matrix44.from_translation((0.0, 0.0, -3.5), dtype='f4')
        model = translation * rotation

        # Render cube to offscreen texture / fbo
        self.fbo.use()
        self.fbo.clear()
        self.ctx.enable(moderngl.DEPTH_TEST | moderngl.CULL_FACE)
        self.prog['m_model'].write(model)
        self.cube.render(self.prog)

        # Render UI to screen
        self.wnd.use()
        self.render_ui()

    def render_ui(self):
        """Render the UI"""
        imgui.new_frame()
        if imgui.begin_main_menu_bar():
            if imgui.begin_menu("File", True):

                clicked_quit, selected_quit = imgui.menu_item(
                    "Quit", 'Cmd+Q', False, True)

                if clicked_quit:
                    exit(1)

                imgui.end_menu()
            imgui.end_main_menu_bar()

        imgui.show_test_window()

        imgui.begin("Custom window", True)
        imgui.text("Bar")
        imgui.text_colored("Eggs", 0.2, 1., 0.)
        imgui.end()

        # Create window with the framebuffer image
        imgui.begin("Custom window with Image", True)
        # Create an image control by passing in the OpenGL texture ID (glo)
        # and pass in the image size as well.
        # The texture needs to he registered using register_texture for this to work
        imgui.image(self.fbo.color_attachments[0].glo, *self.fbo.size)
        imgui.end()

        imgui.render()
        self.imgui.render(imgui.get_draw_data())

    def resize(self, width: int, height: int):
        self.imgui.resize(width, height)

    def key_event(self, key, action, modifiers):
        self.imgui.key_event(key, action, modifiers)

    def mouse_position_event(self, x, y, dx, dy):
        self.imgui.mouse_position_event(x, y, dx, dy)

    def mouse_drag_event(self, x, y, dx, dy):
        self.imgui.mouse_drag_event(x, y, dx, dy)

    def mouse_scroll_event(self, x_offset, y_offset):
        self.imgui.mouse_scroll_event(x_offset, y_offset)

    def mouse_press_event(self, x, y, button):
        self.imgui.mouse_press_event(x, y, button)

    def mouse_release_event(self, x: int, y: int, button: int):
        self.imgui.mouse_release_event(x, y, button)

    def unicode_char_entered(self, char):
        self.imgui.unicode_char_entered(char)
Example #4
0
class MMVShaderMGLWindowHandlers:
    INTENSITY_RESPONSIVENESS = 0.2
    ROTATION_RESPONSIVENESS = 0.2
    ZOOM_RESPONSIVENESS = 0.2
    DRAG_RESPONSIVENESS = 0.3
    DRAG_MOMENTUM = 0.6

    DEVELOPER = False

    def __init__(self, mmv_shader_mgl):
        self.mmv_shader_mgl = mmv_shader_mgl

        # Mouse related controls
        self.target_drag = np.array([0.0, 0.0])
        self.target_intensity = 1
        self.target_rotation = 0
        self.target_zoom = 1

        # Multiplier on top of multiplier, configurable real time
        self.drag_momentum = np.array([0.0, 0.0])
        self.drag = np.array([0.0, 0.0])
        self.intensity = 1
        self.rotation = 0
        self.zoom = 1

        # Keys
        self.shift_pressed = False
        self.ctrl_pressed = False
        self.alt_pressed = False

        # Mouse
        self.mouse_buttons_pressed = []
        self.mouse_exclusivity = False

        # Gui
        self.hide_gui = True

    # Which "mode" to render, window loader class, msaa, ssaa, vsync, force res?
    def mode(self, window_class, msaa=1, vsync=True, strict=False, icon=None):
        debug_prefix = "[MMVShaderMGLWindowHandlers.mode]"

        logging.info(
            f"{debug_prefix} \"i\" Set window mode [window_class={window_class}] [msaa={msaa}] [vsync={vsync}] [strict={strict}] [icon={icon}]"
        )

        # Get function arguments
        self.headless = window_class == "headless"
        self.strict = strict
        self.vsync = vsync
        self.msaa = msaa

        # Headless we disable vsync because we're rendering only..?
        # And also force aspect ratio just in case (strict option)
        if self.headless:
            self.strict = True
            self.vsync = False

        # Assign the function arguments
        settings.WINDOW[
            "class"] = f"moderngl_window.context.{window_class}.Window"
        settings.WINDOW[
            "aspect_ratio"] = self.mmv_shader_mgl.width / self.mmv_shader_mgl.height
        settings.WINDOW["vsync"] = self.vsync
        settings.WINDOW["title"] = "MMVShaderMGL Real Time Window"
        settings.WINDOW["size"] = (self.mmv_shader_mgl.width,
                                   self.mmv_shader_mgl.height)

        # Create the window
        self.window = moderngl_window.create_window_from_settings()

        # Make sure we render strictly into the resolution we asked
        if strict:
            self.window.fbo.viewport = (0, 0, self.mmv_shader_mgl.width,
                                        self.mmv_shader_mgl.height)
            # self.window.set_default_viewport()

        # Set the icon
        if icon is not None:
            # Absolute path
            icon = Path(icon).resolve()
            resources.register_dir(icon.parent)
            self.window.set_icon(icon_path=icon.name)

        # The context we'll use is the one from the window
        self.gl_context = self.window.ctx
        self.mmv_shader_mgl.gl_context = self.gl_context
        self.window_should_close = False

        # Functions of the window if not headless
        if not self.headless:
            self.window.resize_func = self.window_resize
            self.window.key_event_func = self.key_event
            self.window.mouse_position_event_func = self.mouse_position_event
            self.window.mouse_drag_event_func = self.mouse_drag_event
            self.window.mouse_scroll_event_func = self.mouse_scroll_event
            self.window.mouse_press_event_func = self.mouse_press_event
            self.window.mouse_release_event_func = self.mouse_release_event
            self.window.unicode_char_entered_func = self.unicode_char_entered
            self.window.close_func = self.close
            imgui.create_context()
            self.imgui = ModernglWindowRenderer(self.window)

    # [NOT HEADLESS] Window was resized, update the width and height so we render with the new config
    def window_resize(self, width, height):
        if hasattr(self, "strict"):
            if self.strict:
                return

        # Set width and height
        self.mmv_shader_mgl.width = int(width)
        self.mmv_shader_mgl.height = int(height)

        # Recursively call this function on every shader on textures dictionary
        for index in self.mmv_shader_mgl.textures.keys():
            if self.mmv_shader_mgl.textures[index]["loader"] == "shader":
                self.mmv_shader_mgl.textures[index][
                    "shader_as_texture"].window_handlers.window_resize(
                        width=self.mmv_shader_mgl.width,
                        height=self.mmv_shader_mgl.height)

        # Search for dynamic shaders and update them
        for index in self.mmv_shader_mgl.textures.keys():

            # Release Dynamic Shaders and update their target render
            if self.mmv_shader_mgl.textures[index].get("dynamic", False):
                target = self.mmv_shader_mgl.textures[index][
                    "shader_as_texture"]
                target.texture.release()
                target.fbo.release()
                target._create_assing_texture_fbo_render_buffer(verbose=False)

        # Master shader has window and imgui
        if self.mmv_shader_mgl.master_shader:
            if not self.headless:
                self.imgui.resize(self.mmv_shader_mgl.width,
                                  self.mmv_shader_mgl.height)

            # Window viewport
            self.window.fbo.viewport = (0, 0, self.mmv_shader_mgl.width,
                                        self.mmv_shader_mgl.height)

    # Release everything
    def drop_textures(self):
        for index in self.mmv_shader_mgl.textures.keys():
            if "shader_as_texture" in self.mmv_shader_mgl.textures[index].keys(
            ):
                target = self.mmv_shader_mgl.textures[index][
                    "shader_as_texture"]
                target.fullscreen_buffer.release()
                target.program.release()
                target.texture.release()
                target.fbo.release()
                target.vao.release()
            else:
                self.mmv_shader_mgl.textures[index]["texture"].release()

        # Delete items
        for index in list(self.mmv_shader_mgl.textures.keys()):
            del self.mmv_shader_mgl.textures[index]
            gc.collect()

    # Close the window
    def close(self, *args, **kwargs):
        logging.info(f"[MMVShaderMGLWindowHandlers.close] Window should close")
        self.window_should_close = True

    # Swap the window buffers, be careful if vsync is False and you have a heavy
    # shader, it will consume all of your GPU computation and will most likely freeze
    # the video
    def update_window(self):
        self.window.swap_buffers()

        # Interpolate stuff
        self.intensity += (
            self.target_intensity - self.intensity
        ) * MMVShaderMGLWindowHandlers.INTENSITY_RESPONSIVENESS
        self.rotation += (
            self.target_rotation -
            self.rotation) * MMVShaderMGLWindowHandlers.ROTATION_RESPONSIVENESS
        self.zoom += (self.target_zoom - self.zoom
                      ) * MMVShaderMGLWindowHandlers.ZOOM_RESPONSIVENESS
        self.drag += (self.target_drag - self.drag
                      ) * MMVShaderMGLWindowHandlers.DRAG_RESPONSIVENESS
        self.drag_momentum *= MMVShaderMGLWindowHandlers.DRAG_MOMENTUM

        # Drag momentum
        if not 1 in self.mouse_buttons_pressed:
            self.target_drag += self.drag_momentum

    # # Interactive events

    def key_event(self, key, action, modifiers):
        debug_prefix = "[MMVShaderMGLWindowHandlers.key_event]"
        self.imgui.key_event(key, action, modifiers)
        logging.info(
            f"{debug_prefix} Key [{key}] Action [{action}] Modifier [{modifiers}]"
        )

        # Shift and control
        if key == 340: self.shift_pressed = bool(action)
        if key == 341: self.ctrl_pressed = bool(action)
        if key == 342: self.alt_pressed = bool(action)

        # "c" key pressed, reset target rotation
        if (key == 67) and (action == 1):
            logging.info(
                f"{debug_prefix} \"c\" key pressed [Set target rotation to 0]")
            self.target_rotation = 0

        # "e" key pressed, toggle mouse exclusive mode
        if (key == 69) and (action == 1):
            logging.info(
                f"{debug_prefix} \"e\" key pressed [Toggle mouse exclusive]")
            self.mouse_exclusivity = not self.mouse_exclusivity
            self.window.mouse_exclusivity = self.mouse_exclusivity

        # "f" key pressed, toggle fullscreen mode
        if (key == 70) and (action == 1):
            logging.info(
                f"{debug_prefix} \"f\" key pressed [Toggle fullscreen]")
            self.window.fullscreen = not self.window.fullscreen

        # "g" key pressed, toggle gui
        if (key == 71) and (action == 1):
            if MMVShaderMGLWindowHandlers.DEVELOPER:
                logging.info(f"{debug_prefix} \"g\" key pressed [Toggle gui]")
                self.hide_gui = not self.hide_gui

        # "h" key pressed, toggle mouse visible
        if (key == 72) and (action == 1):
            logging.info(
                f"{debug_prefix} \"h\" key pressed [Toggle mouse hidden]")
            self.window.cursor = not self.window.cursor

        # "p" key pressed, screenshot
        if (key == 80) and (action == 1):
            m = self.mmv_shader_mgl  # Lazy

            # Where to save
            now = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
            saveto = m.screenshots_dir / f"{now}.jpg"

            logging.info(
                f"{debug_prefix} \"r\" key pressed, taking screenshot, saving to [{saveto}]"
            )

            # Get data ib the scree's size viewport
            size = (m.width, m.height)
            data = self.window.fbo.read(viewport=(0, 0, size[0], size[1]))

            logging.info(
                f"{debug_prefix} [Resolution: {size}] [WxHx3: {size[0] * size[1] * 3}] [len(data): {len(data)}]"
            )

            # Multiprocess save image to file so we don't lock
            def save_image_to_file(size, data, path):
                img = Image.frombytes('RGB', size, data,
                                      'raw').transpose(Image.FLIP_TOP_BOTTOM)
                img.save(path, quality=95)

            # Start the process
            multiprocessing.Process(target=save_image_to_file,
                                    args=(size, data, saveto)).start()

        # "q" key pressed, quit
        if (key == 81) and (action == 1):
            logging.info(f"{debug_prefix} \"r\" key pressed, quitting")
            self.window_should_close = True

        # "r" key pressed, reload shaders
        if (key == 82) and (action == 1):
            logging.info(
                f"{debug_prefix} \"r\" key pressed [Reloading shaders]")
            self.mmv_shader_mgl._read_shaders_from_paths_again()

        # "s" key pressed, don't pipe pipeline
        if (key == 83) and (action == 1):
            logging.info(
                f"{debug_prefix} \"s\" key pressed [Freezing time and pipelines but resolution, zoom]"
            )
            self.mmv_shader_mgl.freezed_pipeline = not self.mmv_shader_mgl.freezed_pipeline
            for index in self.mmv_shader_mgl.textures.keys():
                if self.mmv_shader_mgl.textures[index]["loader"] == "shader":
                    self.mmv_shader_mgl.textures[index][
                        "shader_as_texture"].freezed_pipeline = self.mmv_shader_mgl.freezed_pipeline

        # "t" key pressed, reset time to zero
        if (key == 84) and (action == 1):
            logging.info(f"{debug_prefix} \"t\" key pressed [Set time to 0]")
            self.mmv_shader_mgl.pipeline["mmv_frame"] = 0
            self.mmv_shader_mgl.pipeline["mmv_time"] = 0

        # "v" key pressed, reset target intensity
        if (key == 86) and (action == 1):
            logging.info(
                f"{debug_prefix} \"v\" key pressed [Set target intensity to 1]"
            )
            self.target_intensity = 1

        # "z" key pressed, reset zoom
        if (key == 90) and (action == 1):
            logging.info(
                f"{debug_prefix} \"z\" key pressed [Set target zoom to 1]")
            self.target_zoom = 1

        # "x" key, reset drag
        if (key == 88) and (action == 1):
            logging.info(
                f"{debug_prefix} \"z\" key pressed [Set target drag to [0, 0]]"
            )
            self.target_drag = np.array([0.0, 0.0])

    # Mouse position changed
    def mouse_position_event(self, x, y, dx, dy):
        self.imgui.mouse_position_event(x, y, dx, dy)
        self.mmv_shader_mgl.pipeline["mmv_mouse"] = [x, y]

        # Drag if on mouse exclusivity
        if self.mouse_exclusivity:
            if self.shift_pressed:
                self.target_zoom += (dy / 1000) * self.target_zoom
            elif self.alt_pressed:
                self.target_rotation += dy / 20
            else:
                self.__apply_rotated_drag(dx=dx,
                                          dy=dy,
                                          howmuch=0.5,
                                          inverse=True)

    # Apply drag with the target rotation (because dx and dy are relative to the window itself not the rendered contents)
    def __apply_rotated_drag(self, dx, dy, howmuch=1, inverse=False):

        # Inverse drag? Feels more natural when mouse exclusivity is on
        inverse = -1 if inverse else 1

        # Add to the mmv_drag pipeline item the dx and dy multiplied by the square of the current zoom
        square_current_zoom = (self.mmv_shader_mgl.pipeline["mmv_zoom"]**2)

        # dx and dy on zoom and SSAA
        dx = (dx * square_current_zoom) * self.mmv_shader_mgl.ssaa
        dy = (dy * square_current_zoom) * self.mmv_shader_mgl.ssaa

        # Cosine and sine
        c = math.cos(math.radians(self.rotation))
        s = math.sin(math.radians(self.rotation))

        # mat2 rotation times the dx, dy vector
        drag_rotated = np.array([(dx * c) + (dy * -s),
                                 (dx * s) + (dy * c)]) * howmuch * inverse

        # Add to target drag the dx, dy relative to current zoom and SSAA level
        self.target_drag += drag_rotated
        self.drag_momentum += drag_rotated

    # Mouse drag, add to pipeline drag
    def mouse_drag_event(self, x, y, dx, dy):
        self.imgui.mouse_drag_event(x, y, dx, dy)

        if 1 in self.mouse_buttons_pressed:
            if self.shift_pressed:
                self.target_zoom += (dy / 1000) * self.target_zoom
            elif self.alt_pressed:
                self.target_rotation += dy / 20
            else:
                self.__apply_rotated_drag(dx=dx, dy=dy, inverse=True)

    # Change SSAA
    def change_ssaa(self, value):
        debug_prefix = "[MMVShaderMGLWindowHandlers.change_ssaa]"
        self.mmv_shader_mgl.ssaa = value
        self.mmv_shader_mgl._read_shaders_from_paths_again()
        logging.info(f"{debug_prefix} Changed SSAA to [{value}]")

    # Zoom in or out (usually)
    def mouse_scroll_event(self, x_offset, y_offset):
        debug_prefix = "[MMVShaderMGLWindowHandlers.mouse_scroll_event]"

        if self.shift_pressed:
            self.target_intensity += y_offset / 10
            logging.info(
                f"{debug_prefix} Mouse scroll with shift Target Intensity: [{self.target_intensity}]"
            )
        elif self.ctrl_pressed:
            change_to = self.mmv_shader_mgl.ssaa + (
                (y_offset / 20) * self.mmv_shader_mgl.ssaa)
            logging.info(
                f"{debug_prefix} Mouse scroll with shift change SSAA to: [{change_to}]"
            )
            self.change_ssaa(change_to)
        elif self.alt_pressed:
            self.target_rotation -= y_offset * 5
            logging.info(
                f"{debug_prefix} Mouse scroll with alt change target rotation to: [{self.target_rotation}]"
            )
        else:
            logging.info(
                f"{debug_prefix} Mouse scroll without shift and ctrl Target Zoom: [{self.target_zoom}]"
            )
            self.target_zoom -= (y_offset * 0.05) * self.target_zoom

        self.imgui.mouse_scroll_event(x_offset, y_offset)

    def mouse_press_event(self, x, y, button):
        debug_prefix = "[MMVShaderMGLWindowHandlers.mouse_press_event]"
        logging.info(
            f"{debug_prefix} Mouse press (x, y): [{x}, {y}] Button [{button}]")
        self.imgui.mouse_press_event(x, y, button)
        if not button in self.mouse_buttons_pressed:
            self.mouse_buttons_pressed.append(button)
        if not self.mouse_exclusivity: self.window.mouse_exclusivity = True

    def mouse_release_event(self, x, y, button):
        debug_prefix = "[MMVShaderMGLWindowHandlers.mouse_release_event]"
        logging.info(
            f"{debug_prefix} Mouse release (x, y): [{x}, {y}] Button [{button}]"
        )
        self.imgui.mouse_release_event(x, y, button)
        if button in self.mouse_buttons_pressed:
            self.mouse_buttons_pressed.remove(button)
        if not self.mouse_exclusivity: self.window.mouse_exclusivity = False

    def unicode_char_entered(self, char):
        self.imgui.unicode_char_entered(char)

    # Render the user interface
    def render_ui(self):

        # Test window
        imgui.new_frame()
        imgui.begin("Custom window", True)
        imgui.text("Bar")
        imgui.text_colored("Eggs", 0.2, 1., 0.)
        imgui.end()

        # Render
        imgui.render()
        self.imgui.render(imgui.get_draw_data())
Example #5
0
class App(mglw.WindowConfig, ABC):
    gl_version = (3, 3)
    title = "App"
    resource_dir = (Path(__file__).parent.parent / 'resources').resolve()
    aspect_ratio = None
    scene: [SceneObject]
    camera: OrthographicCamera

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        imgui.create_context()
        self.imgui = ModernglWindowRenderer(self.wnd)
        self.scene = []
        self.camera = OrthographicCamera((0, 0), 5, self.wnd)

    def render(self, time: float, frametime: float):
        imgui.new_frame()
        self.render_callback(time)
        imgui.render()
        self.imgui.render(imgui.get_draw_data())
        pass

    @abstractmethod
    def render_callback(self, time: float):
        pass

    def resize(self, width: int, height: int):
        self.imgui.resize(width, height)

    def key_event(self, key, action, modifiers):
        self.imgui.key_event(key, action, modifiers)

    def mouse_position_event(self, x, y, dx, dy):
        self.imgui.mouse_position_event(x, y, dx, dy)

    def mouse_drag_event(self, x, y, dx, dy):
        self.imgui.mouse_drag_event(x, y, dx, dy)
        if not imgui.get_io().want_capture_mouse:
            wd = self.camera.unproject_distance(dx, dy)
            control_camera = True
            for o in self.scene:
                o.mouse_drag_event(wd[0], wd[1])
                if o.want_use_mouse:
                    control_camera = False
            if control_camera:
                self.camera.mouse_drag_event(dx, dy)

    def mouse_scroll_event(self, x_offset, y_offset):
        self.imgui.mouse_scroll_event(x_offset, y_offset)
        if not imgui.get_io().want_capture_mouse:
            control_camera = True
            for o in self.scene:
                o.mouse_scroll_event(x_offset, y_offset)
                if o.want_use_mouse:
                    control_camera = False
            if control_camera:
                self.camera.mouse_scroll_event(x_offset, y_offset)

    def mouse_press_event(self, x, y, button):
        self.imgui.mouse_press_event(x, y, button)
        if not imgui.get_io().want_capture_mouse:
            sp = x, self.camera.viewport()[1] - y
            wp = self.camera.unproject(sp[0], sp[1])
            for o in self.scene:
                o.mouse_press_event(wp[0], wp[1], button)

    def mouse_release_event(self, x: int, y: int, button: int):
        self.imgui.mouse_release_event(x, y, button)
        if not imgui.get_io().want_capture_mouse:
            sp = x, self.camera.viewport()[1] - y
            wp = self.camera.unproject(sp[0], sp[1])
            for o in self.scene:
                o.mouse_release_event(wp[0], wp[1], button)

    def unicode_char_entered(self, char):
        self.imgui.unicode_char_entered(char)
Example #6
0
class WindowEvents(mglw.WindowConfig):
    gl_version = (3, 3)
    title = "imgui Integration"
    resource_dir = (Path(__file__).parent / 'resources').resolve()
    aspect_ratio = None

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        imgui.create_context()
        self.imgui = ModernglWindowRenderer(self.wnd)

        self.petr4_h = pd.read_csv("../data/" + selected_symbol + '_yf_data')

        self.candlestick_chart = CandleStickChart(self)
        self.candlestick_chart.set_data(self.petr4_h, csl[csl.Symbol == selected_symbol])

    def render(self, time: float, frametime: float):
        global selected_symbol
        global input_text
        self.candlestick_chart.render()
        imgui.new_frame()
        if imgui.begin_main_menu_bar():
            if imgui.begin_menu("File", True):
                clicked_quit, selected_quit = imgui.menu_item(
                    "Quit", 'Cmd+Q', False, True
                )
                if clicked_quit:
                    exit(1)
                imgui.end_menu()
            changed, value = imgui.input_text("", input_text, 30)
            if changed:
                imgui.set_next_window_position(imgui.get_item_rect_min().x,
                                               imgui.get_item_rect_max().y)
                imgui.set_next_window_size(imgui.get_item_rect_size().x, 0)
                if imgui.begin("##popup", False,
                               imgui.WINDOW_NO_TITLE_BAR | imgui.WINDOW_NO_MOVE | imgui.WINDOW_NO_RESIZE):
                    for index, row in symbol_list.iterrows():
                        if value.upper() in row[0]:
                            opened, selected = imgui.selectable(row[0] + " - " + row[2])
                            if imgui.is_item_clicked():
                                input_text = row[0]
                                selected_symbol = row[0]
                imgui.end()
            if imgui.button("download"):
                yfc.download(selected_symbol, symbol_data_file())
            imgui.end_main_menu_bar()

        if not imgui.get_io().want_capture_mouse:
            self.candlestick_chart.render_gui()
        # if len(df):
        #     graphics.draw_table(df, 0)

        imgui.show_test_window()

        imgui.render()
        self.imgui.render(imgui.get_draw_data())

    def resize(self, width: int, height: int):
        self.imgui.resize(width, height)

    def key_event(self, key, action, modifiers):
        self.imgui.key_event(key, action, modifiers)

    def mouse_position_event(self, x, y, dx, dy):
        self.imgui.mouse_position_event(x, y, dx, dy)

    def mouse_drag_event(self, x, y, dx, dy):
        self.imgui.mouse_drag_event(x, y, dx, dy)
        if not imgui.get_io().want_capture_mouse:
            self.candlestick_chart.mouse_drag_event(dx, dy)

    def mouse_scroll_event(self, x_offset, y_offset):
        self.imgui.mouse_scroll_event(x_offset, y_offset)
        if not imgui.get_io().want_capture_mouse:
            self.candlestick_chart.mouse_scroll_event(x_offset, y_offset)

    def mouse_press_event(self, x, y, button):
        self.imgui.mouse_press_event(x, y, button)
        if not imgui.get_io().want_capture_mouse:
            self.candlestick_chart.mouse_press_event(x, y, button)

    def mouse_release_event(self, x: int, y: int, button: int):
        self.imgui.mouse_release_event(x, y, button)
        if not imgui.get_io().want_capture_mouse:
            self.candlestick_chart.mouse_release_event(x, y, button)

    def unicode_char_entered(self, char):
        self.imgui.unicode_char_entered(char)
class WindowEvents(mglw.WindowConfig):
    gl_version = (3, 3)
    window_size = (1200, 600)
    aspect_ratio = window_size[0] / window_size[1]
    title = "Neural Renderer"

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        imgui.create_context()
        self.wnd.ctx.error
        self.imgui = ModernglWindowRenderer(self.wnd)
        self.space_down = False

        self.prog = self.ctx.program(
            vertex_shader="""
        #version 330
        uniform mat4 transform;
        uniform vec3 clr;
        uniform float aspect;

        in vec3 in_vert;
        out vec3 color;
        out vec2 uv;
        void main() {
            vec3 pos = vec3(in_vert.x, in_vert.y * aspect, 0.0);
            gl_Position = transform * vec4(pos, 1.0);
            uv = vec2(in_vert.x * 0.5 + 0.5, in_vert.y * 0.5 + 0.5);
            uv.y = 1.0 - uv.y;
            color = vec3(1, 0, 0);
        }
        """,
            fragment_shader="""
        #version 330
        uniform sampler2D tex_sampler;

        out vec4 fragColor;
        in vec3 color;
        in vec2 uv;
        void main() {
            fragColor = vec4(texture(tex_sampler, uv).rgb, 1.0);
        }
        """,
        )

        self.reference_texture = self.ctx.texture(
            (dataset.render_size, dataset.render_size), components=3)
        self.prediction_texture = self.ctx.texture(
            (dataset.render_size, dataset.render_size), components=3)
        self.reference_texture.repeat_x = False
        self.reference_texture.repeat_y = False
        self.prediction_texture.repeat_x = False
        self.prediction_texture.repeat_y = False
        self.reference_texture.use(5)
        self.prediction_texture.use(6)

        self.prog['aspect'].value = 12 / 6
        T = pyrr.matrix44.create_from_translation(np.array([-0.5, 0.15, 0]))
        T2 = pyrr.matrix44.create_from_translation(np.array([0.5, 0.15, 0]))
        S = pyrr.matrix44.create_from_scale(np.array([0.4, 0.4, 1]))
        self.M = pyrr.matrix44.multiply(S, T)
        self.M2 = pyrr.matrix44.multiply(S, T2)
        self.transform = self.prog['transform']
        self.transform.value = tuple(self.M.flatten())

        self.observation_textures = []
        self.observation_transforms = []
        for i in range(1, settings.views_per_scene):
            self.observation_textures.append(
                self.ctx.texture((dataset.render_size, dataset.render_size),
                                 components=3))
            self.observation_textures[-1].repeat_x = False
            self.observation_textures[-1].repeat_y = False
            self.observation_textures[-1].use(6 + i)

            T = pyrr.matrix44.create_from_translation(
                np.array([-0.825 + (i - 1) * 0.165, -0.825, 0]))
            S = pyrr.matrix44.create_from_scale(np.array([0.075, 0.075, 1]))
            M = pyrr.matrix44.multiply(S, T)
            self.observation_transforms.append(M)

        self.buffer_textures = []
        self.buffer_transforms = []
        for i in range(len(settings.model.generators[-1].query_passes)):
            self.buffer_textures.append(
                self.ctx.texture((dataset.render_size, dataset.render_size),
                                 components=3))
            self.buffer_textures[-1].repeat_x = False
            self.buffer_textures[-1].repeat_y = False
            self.buffer_textures[-1].use(6 + settings.views_per_scene + i)

            T = pyrr.matrix44.create_from_translation(
                np.array([0.175 + i * 0.165, -0.825, 0]))
            S = pyrr.matrix44.create_from_scale(np.array([0.075, 0.075, 1]))
            M = pyrr.matrix44.multiply(S, T)
            self.buffer_transforms.append(M)

        self.camera = KeyboardCamera(self.wnd.keys, 45.0, 1.0, 0.1, 100.0)
        self.camera.position[0] = 1.5
        self.camera.position[1] = 1.5
        self.camera.position[2] = -1.5
        self.camera._velocity = -2.5
        self.camera._mouse_sensitivity = -0.1

        self.quad = np.array([
            -1.0, -1.0, 0.0, 1.0, -1.0, 0.0, 1.0, 1.0, 0.0, -1.0, -1.0, 0.0,
            1.0, 1.0, 0.0, -1.0, 1.0, 0.0
        ],
                             dtype='f4')
        self.quad_vao = self.ctx.simple_vertex_array(
            self.prog, self.ctx.buffer(self.quad), 'in_vert')

    def render(self, time: float, frametime: float):
        # Load transform
        view = self.camera.matrix
        view_inverse = pyrr.matrix44.inverse(view)
        position = pyrr.matrix44.apply_to_vector(
            view_inverse, np.array([0.0, 0.0, 0.0, 1.0]))
        lookat = pyrr.matrix44.apply_to_vector(view_inverse,
                                               np.array([0.0, 0.0, 1.0, 1.0]))
        dataset.renderer.renderer.set_camera(position[:3], lookat[:3])

        # Get reference and draw
        dataset.samples = samples
        queries = dataset.get_current_view()
        data["query_images"] = queries[0]
        data["query_poses"] = queries[1]

        reference = format_buffer(
            data["query_images"][settings.model.output_pass][0])
        reference = reference.clamp(0, 1).numpy()
        reference = (reference * 255).astype(np.uint8)
        self.reference_texture.write(reference.tobytes())
        self.prog['tex_sampler'].value = 5
        self.transform.value = tuple(self.M.flatten())
        self.quad_vao.render(mode=moderngl.TRIANGLES)

        # Draw observations
        for i in range(len(self.observation_textures)):
            observation = format_buffer(
                data["observation_images"][settings.model.output_pass][0][i])
            observation = observation.clamp(0, 1).numpy()
            observation = (observation * 255).astype(np.uint8)
            self.observation_textures[i].write(observation.tobytes())
            self.prog['tex_sampler'].value = 6 + 1 + i
            self.transform.value = tuple(
                self.observation_transforms[i].flatten())
            self.quad_vao.render(mode=moderngl.TRIANGLES)

        # Draw G-buffer (TODO)
        for i in range(len(self.buffer_textures)):
            buffer = format_buffer(data["query_images"][
                settings.model.generators[-1].query_passes[i]][0])
            buffer = buffer.clamp(0, 1).numpy()
            buffer = (buffer * 255).astype(np.uint8)
            self.buffer_textures[i].write(buffer.tobytes())
            self.prog['tex_sampler'].value = 6 + settings.views_per_scene + i
            self.transform.value = tuple(self.buffer_transforms[i].flatten())
            self.quad_vao.render(mode=moderngl.TRIANGLES)

        # Network sample and draw
        prediction = net.sample(data)
        pred = format_buffer(prediction[-1][settings.model.output_pass][0])
        pred = pred.clamp(0, 1).numpy()
        pred = (pred * 255).astype(np.uint8)
        self.prediction_texture.write(pred.tobytes())
        self.prog['tex_sampler'].value = 6
        self.transform.value = tuple(self.M2.flatten())
        self.quad_vao.render(mode=moderngl.TRIANGLES)

        self.render_ui()

    def render_ui(self):
        global samples, observation_samples
        imgui.new_frame()

        imgui.begin("Options", True)

        if imgui.button("Random Scene"):
            random_scene()

        if imgui.button("Randomize Observations"):
            random_observations()

        _, samples = imgui.drag_int("Query SPP",
                                    samples,
                                    min_value=1,
                                    max_value=1024)
        _, observation_samples = imgui.drag_int("Observation SPP",
                                                observation_samples,
                                                min_value=1,
                                                max_value=1024)

        imgui.end()

        imgui.render()
        self.imgui.render(imgui.get_draw_data())

    def resize(self, width: int, height: int):
        self.imgui.resize(width, height)

    def key_event(self, key, action, modifiers):
        global samples, observation_samples
        self.imgui.key_event(key, action, modifiers)
        if action == self.wnd.keys.ACTION_PRESS:
            if key == self.wnd.keys.SPACE:
                self.space_down = True
            if key == self.wnd.keys.R:
                random_scene()
            if key == self.wnd.keys.O:
                random_observations()
            if key == self.wnd.keys.J:
                samples += 10
            if key == self.wnd.keys.H:
                samples = max(1, samples - 10)
            if key == self.wnd.keys.M:
                observation_samples += 10
            if key == self.wnd.keys.N:
                observation_samples = max(1, observation_samples - 10)

        if action == self.wnd.keys.ACTION_RELEASE:
            if key == self.wnd.keys.SPACE:
                self.space_down = False
                imgui.set_window_focus()

        if self.space_down:
            self.camera.key_input(key, action, modifiers)

    def mouse_position_event(self, x, y, dx, dy):
        self.imgui.mouse_position_event(x, y, dx, dy)

    def mouse_drag_event(self, x, y, dx, dy):
        self.imgui.mouse_drag_event(x, y, dx, dy)
        if self.space_down:
            self.camera.rot_state(dx, dy)

    def mouse_scroll_event(self, x_offset, y_offset):
        self.imgui.mouse_scroll_event(x_offset, y_offset)

    def mouse_press_event(self, x, y, button):
        self.imgui.mouse_press_event(x, y, button)

    def mouse_release_event(self, x: int, y: int, button: int):
        self.imgui.mouse_release_event(x, y, button)

    def unicode_char_entered(self, char):
        self.imgui.unicode_char_entered(char)