64 lines
5.7 KiB
Markdown
64 lines
5.7 KiB
Markdown
# 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](https://en.wikipedia.org/wiki/Nerv) 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](guide_nerv_theme.md) (placeholder; written in Task 10) for the full theme API, configuration keys, and customization options.
|