From cbf7bf353904c3462cb60665f86ad3940c3b5527 Mon Sep 17 00:00:00 2001 From: Samuel Onoja Date: Fri, 25 Sep 2026 05:45:24 +0100 Subject: [PATCH] fix: make glass backdrop visibly blur --- compositor/src/effects.rs | 12 ++++++---- compositor/src/winit.rs | 31 +++++++++++++++++--------- tools/ferese-effects-probe/src/main.rs | 6 ++--- 3 files changed, 31 insertions(+), 18 deletions(-) diff --git a/compositor/src/effects.rs b/compositor/src/effects.rs index 38adf4b..a961f9b 100644 --- a/compositor/src/effects.rs +++ b/compositor/src/effects.rs @@ -41,7 +41,7 @@ pub(crate) struct ResolvedMaterial { } pub(crate) fn resolve_material(role: SemanticRole, style: MaterialStyle) -> ResolvedMaterial { - let (opacity, blur, saturation, brightness, noise) = match role { + let (base_opacity, blur, saturation, brightness, noise) = match role { SemanticRole::Panel => (0.78, 24.0, 1.08, 1.02, 0.012), SemanticRole::PanelElevated | SemanticRole::Popover @@ -53,7 +53,11 @@ pub(crate) fn resolve_material(role: SemanticRole, style: MaterialStyle) -> Reso match style { MaterialStyle::Glass => ResolvedMaterial { style, - opacity, + // Glass already contains an opaque copy of the backdrop. Its tint + // therefore needs less coverage than the no-capture translucent + // profile or the blur becomes visually indistinguishable from a + // flat alpha surface. + opacity: base_opacity * 0.72, blur, saturation, brightness, @@ -61,7 +65,7 @@ pub(crate) fn resolve_material(role: SemanticRole, style: MaterialStyle) -> Reso }, MaterialStyle::Translucent => ResolvedMaterial { style, - opacity, + opacity: base_opacity, blur: 0.0, saturation: 1.0, brightness: 1.0, @@ -299,7 +303,7 @@ mod tests { assert!(glass.blur > 0.0); assert!(glass.noise > 0.0); - assert_eq!(translucent.opacity, glass.opacity); + assert!(glass.opacity < translucent.opacity); assert_eq!(translucent.blur, 0.0); assert_eq!(translucent.noise, 0.0); assert_eq!(solid.opacity, 1.0); diff --git a/compositor/src/winit.rs b/compositor/src/winit.rs index e2c487d..3570248 100644 --- a/compositor/src/winit.rs +++ b/compositor/src/winit.rs @@ -261,6 +261,17 @@ float random(vec2 point) { return fract(sin(dot(point, vec2(12.9898, 78.233))) * 43758.5453); } +float kernel_weight(int tap) { + int distance = tap < 0 ? -tap : tap; + if (distance == 0) { + return 6.0; + } + if (distance == 1) { + return 4.0; + } + return 1.0; +} + void main() { vec2 point = gl_FragCoord.xy; vec2 visible_max = visible_rect.xy + visible_rect.zw; @@ -270,16 +281,16 @@ void main() { return; } - vec2 step_size = vec2(blur_radius) / max(texture_size, vec2(1.0)); - vec4 color = texture2D(tex, v_coords) * 0.20; - color += texture2D(tex, v_coords + vec2(step_size.x, 0.0)) * 0.12; - color += texture2D(tex, v_coords - vec2(step_size.x, 0.0)) * 0.12; - color += texture2D(tex, v_coords + vec2(0.0, step_size.y)) * 0.12; - color += texture2D(tex, v_coords - vec2(0.0, step_size.y)) * 0.12; - color += texture2D(tex, v_coords + step_size) * 0.08; - color += texture2D(tex, v_coords - step_size) * 0.08; - color += texture2D(tex, v_coords + vec2(step_size.x, -step_size.y)) * 0.08; - color += texture2D(tex, v_coords + vec2(-step_size.x, step_size.y)) * 0.08; + vec2 step_size = vec2(blur_radius * 0.5) / max(texture_size, vec2(1.0)); + vec4 color = vec4(0.0); + for (int y = -2; y <= 2; y++) { + for (int x = -2; x <= 2; x++) { + float weight = kernel_weight(x) * kernel_weight(y); + vec2 offset = vec2(float(x), float(y)) * step_size; + color += texture2D(tex, v_coords + offset) * weight; + } + } + color /= 256.0; float luma = dot(color.rgb, vec3(0.2126, 0.7152, 0.0722)); vec3 adjusted = mix(vec3(luma), color.rgb, saturation) * brightness; diff --git a/tools/ferese-effects-probe/src/main.rs b/tools/ferese-effects-probe/src/main.rs index 47398a7..a6d8252 100644 --- a/tools/ferese-effects-probe/src/main.rs +++ b/tools/ferese-effects-probe/src/main.rs @@ -70,11 +70,9 @@ fn main() -> Result<(), Box> { } if preview { - effects.set_role(ferese_surface_effects_v1::Role::Popover); + effects.set_role(ferese_surface_effects_v1::Role::Panel); queue.roundtrip(&mut state)?; - println!( - "PREVIEW glass popover is mapped; press Ctrl+C in the compositor terminal to stop" - ); + println!("PREVIEW glass panel is mapped over the patterned card; press Ctrl+C to stop"); while !state.closed { queue.blocking_dispatch(&mut state)?;