fix(acrylic): frost glass panels at full strength (slider was a near no-op)

The per-panel acrylic composite drew the blurred capture at
`fallbackColor.w * uiOpacity` alpha. At a lowered UI opacity that's ~24%, so the
SHARP background bled straight through the panels — the acrylic slider changed
almost nothing (measured: blur 0% vs 100% differed in 0.33% of pixels, and the
marbled background was equally crisp at both).

Draw the blurred capture at (near) full strength so it actually FROSTS the panel
(the blurred background replaces the sharp one); UI opacity now scales only the
tint overlay in DrawGlassPanel, which is the correct acrylic model — opacity =
tint, not sharp-vs-blur. Fixed symmetrically in both the GL and DX11 drawRect
paths. Verified on GL: blur 0% now shows a sharp background, 100% a smooth
frosted wash (0.33% -> 8.3% pixels changed), and the default (high-opacity) card
look is unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-10 19:46:18 -05:00
parent a5efbaf83d
commit 433c7ae46f

View File

@@ -586,12 +586,14 @@ void AcrylicMaterial::drawRect(ImDrawList* drawList, const ImVec2& pMin, const I
float u1 = localX1 / viewportWidth_;
float v1 = 1.0f - localY1 / viewportHeight_; // V at bottom-right (low)
// Draw the blurred background. Scale by both the glass preset
// opacity (fallbackColor.w) AND the user's UI opacity slider so
// that lowering card opacity lets the sharp background through.
// Draw the blurred background at (near) full strength so the panel is actually FROSTED — the
// blurred capture replaces the sharp background in the card. UI opacity is applied only to the
// tint overlay (in DrawGlassPanel), NOT here: scaling the blur by uiOpacity used to let the
// SHARP background bleed straight through at low opacity, which made the acrylic slider look
// like a no-op. A small floor keeps it frosted even for low-alpha presets.
ImTextureID blurTex = getBlurredTexture();
uint8_t glassAlpha = static_cast<uint8_t>(
std::min(255.0f, std::max(0.0f, params.fallbackColor.w * settings_.uiOpacity * 255.0f)));
std::min(255.0f, std::max(0.0f, std::max(params.fallbackColor.w, 0.90f) * 255.0f)));
if (blurTex) {
drawList->AddImageRounded(
@@ -1562,11 +1564,12 @@ void AcrylicMaterial::drawRect(ImDrawList* drawList, const ImVec2& pMin, const I
(void*)blurTex, u0, v0, u1, v1);
}
// Draw the blurred background. Scale by both the glass preset
// opacity (fallbackColor.w) AND the user's UI opacity slider so
// that lowering card opacity lets the sharp background through.
// Draw the blurred background at (near) full strength so the panel is actually FROSTED — UI
// opacity is applied only to the tint overlay, NOT here (scaling the blur by uiOpacity let the
// SHARP background bleed through at low opacity, making the acrylic slider a no-op). Mirrors the
// GL drawRect fix above.
uint8_t glassAlpha = (uint8_t)std::min(255.f,
std::max(0.f, params.fallbackColor.w * settings_.uiOpacity * 255.f));
std::max(0.f, std::max(params.fallbackColor.w, 0.90f) * 255.f));
if (blurTex) {
drawList->AddImageRounded(