feat(effects): overlay-time live-framebuffer blur behind the portfolio modal

The acrylic system only blurred a frozen snapshot of the static app background. Add
an overlay-time re-capture so the Manage-portfolio modal blurs the LIVE tab content
behind it.

- AcrylicMaterial::captureLiveFramebuffer() (GL blit of FB 0 / DX11 CopyResource of the
  backbuffer + no-backend stub) mirrors captureBackgroundDirect but bypasses the
  dirtyFrames_ gate so it refreshes every frame the overlay is open, forcing a re-blur.
- ImGuiAcrylic::GetLiveCaptureCallback() returns a draw callback for it.
- market_tab: the modal inserts that callback (+ ImDrawCallback_ResetRenderState) at the
  START of its overlay draw list, before the backdrop, so the capture holds the app UI
  drawn below and the backdrop blurs it. On close, InvalidateCapture() re-captures the
  background so other glass panels don't keep blurring the stale live capture.
- Panel theme-effects are suppressed during the market render while the modal is open
  (their foreground-draw-list borders draw above all windows and would otherwise bleed
  over the overlay). Market tab body is rendered again (no longer skipped).
- Backdrop draws the acrylic at full strength (fallbackColor.w=1) over an opaque base so
  the blurred content reads clearly; lighter dim.

Design mapped via an Explore investigation of the capture/blur pipeline; compiles on
both OpenGL (Linux) and DX11 (Windows cross-build). Needs on-device visual verification.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-03 20:26:11 -05:00
parent 2035f71c65
commit 0e8816e220
6 changed files with 95 additions and 9 deletions

View File

@@ -484,13 +484,14 @@ inline void DrawGlassPanel(ImDrawList* dl, const ImVec2& pMin,
// mirroring DrawGlassPanel's gating.
inline void DrawFullWindowBlurBackdrop(ImDrawList* dl, const ImVec2& pMin, const ImVec2& pMax)
{
dl->AddRectFilled(pMin, pMax, IM_COL32(9, 10, 16, 255)); // opaque base — guarantees opacity
dl->AddRectFilled(pMin, pMax, IM_COL32(9, 10, 16, 255)); // opaque base (shows through if the blur is faint)
if (IsBackdropActive() && !dragonx::ui::effects::isLowSpecMode()
&& effects::ImGuiAcrylic::IsEnabled() && effects::ImGuiAcrylic::IsAvailable()) {
auto params = GetCurrentAcrylicTheme().card;
params.blurRadius = 40.0f; // strong — spans the whole window
params.fallbackColor.w = 1.0f; // full-strength blur so the live content reads
effects::ImGuiAcrylic::DrawAcrylicRect(dl, pMin, pMax, params, 0.0f);
dl->AddRectFilled(pMin, pMax, IM_COL32(6, 8, 18, 90)); // dim so the card reads as foreground
dl->AddRectFilled(pMin, pMax, IM_COL32(6, 8, 18, 70)); // slight dim so the card reads as foreground
}
}