feat(modals): fixed modal-backdrop blur, independent of the acrylic slider

The modal backdrop blur was params.blurRadius (96) scaled by the user's global
acrylic blur-strength slider (blurRadiusMultiplier), so lowering the slider also
weakened every modal's backdrop. Make the modal blur a fixed hardcoded value.

Add AcrylicParams::absoluteBlurRadius: when set, applyBlur() uses the radius
as-is and skips the multiplier (threaded through both the GL and DX11 blur paths
+ the no-op stub). DrawFullWindowBlurBackdrop sets it, so the modal backdrop is
always a 96px blur regardless of the slider. Panels/other acrylic still scale
with the slider as before.

Verified: rendering a modal at blur_multiplier 0.1 vs 2.0 now produces an
identical backdrop (max pixel diff 1/255) — previously those were ~9.6px vs
~192px of blur.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-12 07:41:53 -05:00
parent 2f86bec98e
commit 156735eb06
3 changed files with 17 additions and 11 deletions

View File

@@ -388,14 +388,14 @@ void AcrylicMaterial::setQuality(AcrylicQuality quality)
}
}
void AcrylicMaterial::applyBlur(float radius)
void AcrylicMaterial::applyBlur(float radius, bool ignoreMultiplier)
{
if (!blurBuffers_.isValid() || !blurShader_.isValid()) {
return;
}
// Apply blur radius multiplier from settings
float scaledRadius = radius * settings_.blurRadiusMultiplier;
// Apply the user's blur-strength multiplier — unless the caller wants an absolute radius.
float scaledRadius = ignoreMultiplier ? radius : radius * settings_.blurRadiusMultiplier;
// Skip blur entirely when multiplier is at or near zero — show sharp background
if (scaledRadius < 0.5f) {
@@ -566,7 +566,7 @@ void AcrylicMaterial::drawRect(ImDrawList* drawList, const ImVec2& pMin, const I
}
// Apply blur to captured background
applyBlur(params.blurRadius);
applyBlur(params.blurRadius, params.absoluteBlurRadius);
// Calculate UV coordinates for sampling the blur FBO texture.
// With multi-viewport enabled, ImGui draw coordinates are in
@@ -1274,11 +1274,11 @@ void AcrylicMaterial::captureLiveFramebuffer()
blurCacheValid_ = false;
}
void AcrylicMaterial::applyBlur(float radius)
void AcrylicMaterial::applyBlur(float radius, bool ignoreMultiplier)
{
if (!dx_blurSRV_[0] || !dx_blurPS_ || !dx_context_) return;
float scaledRadius = radius * settings_.blurRadiusMultiplier;
float scaledRadius = ignoreMultiplier ? radius : radius * settings_.blurRadiusMultiplier;
if (blurCacheValid_ && std::abs(scaledRadius - lastBlurRadius_) < 0.1f) return;
int passes = 1;
@@ -1540,7 +1540,7 @@ void AcrylicMaterial::drawRect(ImDrawList* drawList, const ImVec2& pMin, const I
}
// Run DX11 blur pipeline
applyBlur(params.blurRadius);
applyBlur(params.blurRadius, params.absoluteBlurRadius);
// DX11 UV: top-left = (0,0), bottom-right = (1,1) — same as ImGui
// With multi-viewport, pMin/pMax are in OS screen space; subtract
@@ -1704,7 +1704,7 @@ void AcrylicMaterial::resize(int, int) {}
void AcrylicMaterial::captureBackground() {}
void AcrylicMaterial::captureBackgroundDirect() {}
void AcrylicMaterial::captureLiveFramebuffer() {}
void AcrylicMaterial::applyBlur(float) {}
void AcrylicMaterial::applyBlur(float, bool) {}
ImTextureID AcrylicMaterial::getBlurredTexture() const { return 0; }
ImTextureID AcrylicMaterial::getNoiseTexture() const { return 0; }
void AcrylicMaterial::refreshCapabilities() {}

View File

@@ -39,7 +39,12 @@ struct AcrylicParams {
// Blur radius in pixels (typical: 20-60)
float blurRadius = 30.0f;
// When true, blurRadius is used AS-IS — NOT scaled by the user's blur-strength slider
// (blurRadiusMultiplier). The modal backdrop sets this so its blur is a fixed value, independent
// of the global acrylic slider.
bool absoluteBlurRadius = false;
// Noise texture opacity (typical: 0.02-0.04)
float noiseOpacity = 0.02f;
@@ -341,7 +346,7 @@ private:
/**
* @brief Apply blur passes to captured content
*/
void applyBlur(float radius);
void applyBlur(float radius, bool ignoreMultiplier = false);
/**
* @brief Composite final acrylic appearance

View File

@@ -743,6 +743,7 @@ inline void DrawFullWindowBlurBackdrop(ImDrawList* dl, const ImVec2& pMin, const
// caller — no other radius contends for the shared, radius-keyed blur cache.
auto params = GetCurrentAcrylicTheme().card;
params.blurRadius = 96.0f; // strong full-window blur (deeper than panels)
params.absoluteBlurRadius = true; // fixed modal blur — independent of the user's acrylic slider
params.fallbackColor.w = 1.0f; // full-strength blur so the live content reads
effects::ImGuiAcrylic::DrawAcrylicRect(dl, pMin, pMax, params, 0.0f);
// Dim over the blur so the floating (card-less) modal reads as foreground. On DARK themes the