Private
Public Access
0
0
Files
manual_slop/docs/guide_shaders_and_window.md
T

5.7 KiB
Raw Blame History

Custom Shaders and Window Frame Architecture

1. Shader Injection Strategy

Evaluation

  • Dear PyGui (Legacy): Does not natively support raw GLSL/HLSL shader injection into the UI layer. It relies heavily on fixed-function vertex/fragment shaders compiled into the C++ core. Faux-shaders via DrawList are the only viable path without modifying the DPG source.
  • imgui-bundle (Current): imgui-bundle utilizes hello_imgui as its application runner, which provides robust lifecycle callbacks (e.g., callbacks.custom_background, callbacks.post_init). Because hello_imgui exposes the underlying OpenGL context, we can use PyOpenGL alongside it to execute raw GLSL shaders.

Chosen Approach: Hybrid Faux-Shader & PyOpenGL FBO

Given the Python environment, we will adopt a hybrid approach:

  1. Faux-Shaders (ImDrawList Batching): Continue using imgui.ImDrawList primitives for simple effects like soft shadows, glows, and basic gradients (as seen in src/shaders.py). This is highly performant for UI elements and requires no external dependencies.
  2. True GPU Shaders (PyOpenGL + FBO): For complex post-processing (CRT curvature, bloom, dynamic noise backgrounds), we will integrate PyOpenGL.
    • We will compile GLSL shaders during post_init.
    • We will render the effect into a Framebuffer Object (FBO).
    • We will display the resulting texture ID using imgui.image() or inject it into the custom_background callback.

Note: This approach introduces PyOpenGL as a dependency, which is standard for advanced Python graphics.

2. Custom Window Frame Strategy

Evaluation

  • Native DWM Overloading (PyWin32): It is possible to use pywin32 to subclass the application window, intercept WM_NCHITTEST, and return HTCAPTION for a custom ImGui-drawn title bar region. This preserves Windows snap layouts and native drop shadows. However, it is strictly Windows-only and can conflict with GLFW/SDL2 event loops used by hello_imgui.
  • Borderless Window Mode (ImGui/GLFW): hello_imgui allows configuring the main window as borderless/undecorated (runner_params.app_window_params.borderless = True). We must then manually draw the title bar, minimize/maximize/close buttons, and handle window dragging by updating the OS window position based on ImGui mouse drag deltas.

Chosen Approach: Pure ImGui Borderless Implementation

To ensure cross-platform compatibility and avoid brittle Win32 hook collisions with hello_imgui, we will use the Borderless Window Mode approach.

  1. Initialization: Configure hello_imgui.RunnerParams to disable OS window decorations.
  2. Title Bar Rendering: Dedicate the top ~30 pixels of the ImGui workspace to a custom title bar that matches the current theme (e.g., NERV or standard).
  3. Window Controls: Implement custom ImGui buttons for _, [], and X, which will call native window management functions exposed by hello_imgui or glfw.
  4. Drag Handling: Detect imgui.is_mouse_dragging() on the title bar region and dynamically adjust the application window position.

3. Integration with Event Metrics

Both the shader uniforms (time, resolution) and window control events will be hooked into the existing dag_engine and events systems to ensure minimal performance overhead and centralized configuration via config.toml.


4. NERV Theme Effects

The NERV Technical Console theme (src/theme_nerv.py, src/theme_nerv_fx.py) is a selectable high-density visual variant that uses the shader and window-frame infrastructure above to produce a CRT-style "Tactical Console" aesthetic.

Visual Characteristics

  • Black Void Palette: Near-black backgrounds with sharp, high-contrast accents.
  • Zero-Rounding Geometry: No rounded corners on panels, buttons, or frames. Sharp rectangles.
  • CRT Scanlines: A repeating horizontal line overlay drawn into the foreground draw list by CRTFilter.render(width, height) in src/theme_nerv_fx.py:8-65. Alphas are hard-coded (0.08 major / 0.04 minor) — not config-driven.
  • Status Flickering: StatusFlicker.get_alpha() in src/theme_nerv_fx.py:67-73 returns a hard-coded 3.18 Hz sine (angular frequency 20.0 rad/s). Not wired into a production caller as of 2026-06-10.
  • Alert Animations: AlertPulsing.update(status) at src/theme_nerv_fx.py:79-83 activates the red border pulse for any status.lower().startswith("error"); the pulse persists for the duration of that status (no auto-decay).

Implementation Files

  • src/theme_nerv.py — Color palette, geometry overrides, font selection.
  • src/theme_nerv_fx.py — Scanline overlay, status flickering, alert animations.
  • src/bg_shader.py — Custom background shader (uses the FBO pipeline described in Section 1).

Activation

The NERV theme is selected via the GUI's theme picker (NERV is one of the built-in syntax palettes in the multi-theme TOML system). When activated, theme_nerv.apply_nerv() swaps the active color set and zero-rounding geometry. The FX layer's CRTFilter.enabled is toggled per-frame by the caller of theme_2.render_post_fx(crt_enabled=...) — there is no [nerv].fx_enabled config key.

Performance Considerations

CRT scanlines run at full window resolution via CRTFilter.render()'s draw-list calls (no FBO/shader pass in the current implementation). On a 1920×1080 display, the per-frame cost is on the order of 1-2ms. For lower-end GPUs, the only knob is CRTFilter.enabled (set by the caller of theme_2.render_post_fx(crt_enabled=...)); the scanline alpha and noise density are hard-coded in src/theme_nerv_fx.py.

See guide_nerv_theme.md (placeholder; written in Task 10) for the full theme API, configuration keys, and customization options.