Liquid Glass for Hyprland.
Frosted blur, edge refraction, chromatic aberration, specular highlights — fully customizable, per-theme, on every window and layer surface.
| Dark | Light |
|---|---|
![]() |
![]() |
Builds against your exact Hyprland version, no ABI mismatch headaches:
hyprpm add https://github.com/hyprnux/hyprglass
hyprpm enable hyprglassGrab hyprglass.so from Releases. Each release targets a specific Hyprland API version — check the release notes to confirm it matches yours.
hyprctl plugin load /path/to/hyprglass.soOr persist it in your config:
plugin = /path/to/hyprglass.somake
hyprctl plugin load $(pwd)/hyprglass.soThe plugin must be loaded before configuring it. Wrap everything in a guard:
if hl.plugin.hyprglass then
local hg = hl.plugin.hyprglass
hg.config({
default_theme = "dark",
default_preset = "clear",
tint_color = 0x8899aa22,
brightness = 0.9,
dark = { brightness = 0.82 },
light = { adaptive_boost = 0.5 },
layers = { enabled = 1 },
})
-- Layer surfaces: each call whitelists the namespace and configures it
hg.layer("waybar", { preset = "subtle", mask_threshold = 0.05 })
hg.layer("swaync")
hg.layer("quickshell:bezel", { preset = "ui", mask_threshold = 0.3 })
hg.layer("debug-panel", { exclude = true })
-- Presets
hg.preset("clear", {
glass_opacity = 0.8,
blur_strength = 1.5,
dark = { brightness = 0.7 },
light = { brightness = 1.2 },
})
hg.preset("contrasted", {
inherits = "high_contrast",
contrast = 1.2,
adaptive_dim = 1.5,
dark = { tint_color = 0x02142aa9 },
})
endDeprecated as of Hyprland 0.55, but still supported.
plugin:hyprglass {
default_theme = dark
default_preset = clear
tint_color = 0x8899aa22
brightness = 0.9
dark:brightness = 0.82
light:adaptive_boost = 0.5
preset = name:clear, glass_opacity:0.8, blur_strength:1.5
preset = name:clear:dark, brightness:0.7
preset = name:clear:light, brightness:1.2
preset = name:contrasted, inherits:high_contrast, contrast:1.2, adaptive_dim:1.5
preset = name:contrasted:dark, tint_color:0x02142aa9
layers {
enabled = 1
namespaces = waybar, swaync, quickshell:bezel
exclude_namespaces = debug-panel
preset = subtle
namespace_presets = quickshell:bezel:ui
namespace_mask_thresholds = waybar=0.05, quickshell:bezel=0.3
}
}| Option | Type | Default | Description |
|---|---|---|---|
enabled |
bool | true (1 in .conf) |
Enable/disable the effect globally. Per-window tags override this. |
default_theme |
string | dark |
Default theme: dark or light |
default_preset |
string | default |
Default preset name |
Set globally, per theme (dark: / light: prefix in .conf, or dark = {} / light = {} table in Lua), or in a preset.
Settings resolve through: preset chain (theme variant, shared, inherited) then theme override then global value then hardcoded default.
| Option | Type | Global Default | Dark Default | Light Default | Description |
|---|---|---|---|---|---|
blur_strength |
float | 2.0 |
— | — | Blur radius scale (value * 12.0 px) |
blur_iterations |
int | 3 |
— | — | Gaussian blur passes (1-5) |
refraction_strength |
float | 0.6 |
— | — | Edge refraction intensity (0.0-1.0) |
chromatic_aberration |
float | 0.5 |
— | — | Spectral dispersion at edges (0.0-1.0) |
fresnel_strength |
float | 0.6 |
— | — | Edge glow intensity (0.0-1.0) |
specular_strength |
float | 0.8 |
— | — | Specular highlight brightness (0.0-1.0) |
glass_opacity |
float | 1.0 |
— | — | Overall glass opacity (0.0-1.0) |
edge_thickness |
float | 0.06 |
— | — | Bezel width, fraction of smallest dimension (0.0-0.15) |
tint_color |
color | 0x8899aa22 |
— | — | Glass tint RRGGBBAA hex. Alpha = tint strength |
lens_distortion |
float | 0.5 |
— | — | Center dome magnification (0.0-1.0) |
brightness |
float | — | 0.82 |
1.12 |
Brightness multiplier |
contrast |
float | — | 0.90 |
0.92 |
Contrast around midpoint |
saturation |
float | — | 0.80 |
0.85 |
Desaturation (0 = grayscale, 1 = full) |
vibrancy |
float | — | 0.15 |
0.12 |
Selective saturation boost |
vibrancy_darkness |
float | — | 0.0 |
0.0 |
Vibrancy influence on dark areas (0-1) |
adaptive_dim |
float | — | 0.4 |
0.0 |
Dims bright areas behind the glass (white is white 0 -to- 1 white becomes black) |
adaptive_boost |
float | — | 0.0 |
0.4 |
Boosts dark areas behind the glass (black is black 0 -to- 1 black becomes white) |
— in Global Default = falls through to per-theme default. — in Dark/Light = inherits global value.
The glass effect can be applied to layer surfaces (bars, docks, widgets). Disabled by default.
The effect uses the layer surface opacity as a mask:
- Partially transparent content (down to ~0.004 opacity) triggers the glass effect
- Fully transparent areas are ignored
Caveat: Layer shadows count as visible content. Use mask_threshold to set an alpha cutoff higher than your shadow opacity.
hg.config({ layers = { enabled = true } })
-- Each call whitelists the namespace and optionally configures it
hg.layer("waybar", { preset = "subtle", mask_threshold = 0.05 })
hg.layer("swaync")
hg.layer("quickshell:bezel", { preset = "ui", mask_threshold = 0.3 })
hg.layer("debug-panel", { exclude = true })| Field | Type | Description |
|---|---|---|
preset |
string | Preset override for this layer |
mask_threshold |
float | Alpha threshold (pixels below this are not glassed). Default 0.001 |
exclude |
bool | Blacklist this namespace instead of whitelisting it |
| Option | Type | Default | Description |
|---|---|---|---|
layers:enabled |
bool | false (0 in .conf) |
Enable glass on layer surfaces |
layers:namespaces |
string | "" |
Comma-separated namespace whitelist. Empty = all layers |
layers:exclude_namespaces |
string | "" |
Comma-separated namespace blacklist (priority over whitelist) |
layers:preset |
string | "" |
Preset override for all layers |
layers:namespace_presets |
string | "" |
Per-namespace preset (ns:preset pairs, comma-separated) |
layers:namespace_mask_thresholds |
string | "" |
Per-namespace alpha threshold (ns=value pairs, comma-separated) |
Layer support hooks into Hyprland's internal render pipeline. This is version-sensitive and may break across Hyprland updates.
Control the effect, theme, and preset per window via tags.
Override the global enabled setting per window via tags:
hyprglass_disabled— force the effect off on this window (wins overhyprglass_enabledif both present).hyprglass_enabled— force the effect on this window. Useful with globalenabled = falsefor a whitelist.
Each window's theme is resolved as:
- Window tag
hyprglass_theme_lightorhyprglass_theme_dark - Fallback to
default_theme
Assign via window rules:
hyprglass_preset_<name>— overridedefault_presetfor this window
Lua:
hl.window_rule({ match = { class = "mpv" }, tag = "+hyprglass_disabled" })
hl.window_rule({ match = { fullscreen = true }, tag = "+hyprglass_disabled" })
hl.window_rule({ match = { class = "firefox" }, tag = "+hyprglass_theme_light" })
hl.window_rule({ match = { class = "myterminal" }, tag = "+hyprglass_preset_high_contrast" })Legacy .conf:
windowrule = tag +hyprglass_disabled, class:mpv
windowrule = tag +hyprglass_disabled, fullscreen:1
windowrule = tag +hyprglass_theme_light, class:firefox
windowrule = tag +hyprglass_preset_high_contrast, class:myterminalOn the fly:
hyprctl dispatch tagwindow +hyprglass_disabled
hyprctl dispatch tagwindow +hyprglass_theme_dark
hyprctl dispatch tagwindow +hyprglass_preset_subtlePresets are named config overrides. They can be built-in or user-defined. User presets with the same name override built-in ones.
Each preset can have shared values (theme-agnostic), a dark variant, a light variant, and can inherit from another preset.
Always available. Activate via default_preset or per-window tags.
| Preset | Description |
|---|---|
high_contrast |
Punchy colors, strong tinting, good contrast between dark and light themes. Lower blur, stronger refraction. |
subtle |
Minimal glass effect. Light blur, reduced refraction and highlights. |
clear |
Minimal transparent effect. Like a transparent rounded border glass plate. |
glass |
Solid glass block effect with a lot of chromatic aberration. |
Note: These presets are starting points. Submit improvements or your own presets through issues or PRs (with screenshots).
Lua (table syntax):
hg.preset("clear", {
glass_opacity = 0.8,
blur_strength = 1.5,
inherits = "subtle",
dark = { brightness = 0.7 },
light = { brightness = 1.2 },
})Lua (string syntax, backward compat):
hg.preset("name:clear, glass_opacity:0.8, blur_strength:1.5")
hg.preset("name:clear:dark, brightness:0.7")Legacy .conf:
preset = name:clear, glass_opacity:0.8, blur_strength:1.5
preset = name:clear:dark, brightness:0.7
preset = name:clear:light, brightness:1.2
preset = name:contrasted, inherits:high_contrast, contrast:1.2Tip: increase the last two hex digits of tint_color for more tint opacity.
The window/layer is modeled as a thick convex glass slab. The rendering pipeline per window:
- Background sampling — The framebuffer behind the window is captured with padding (content beyond the window boundary is included).
- Gaussian blur — Multi-pass two-pass (horizontal + vertical) Gaussian blur for the frosted look.
- Glass height field — An SDF-based height profile: 1.0 deep inside the window, smooth S-curve to 0.0 at the edge. The transition width is
edge_thickness. - Edge refraction — The height field gradient drives UV displacement. At the center the gradient is near-zero (no distortion). At the edges the gradient is steep, pushing sample UVs outward — pulling in content from beyond the window boundary. This creates natural color bleeding.
- Chromatic aberration — R, G, B channels are sampled with slightly different refraction scales (blue bends more), creating spectral fringing at edges.
- Center dome lens — Subtle barrel magnification in the flat interior, controlled by
lens_distortion. - Frosted tint — Per-theme tone mapping: adaptive luminance-dependent brightness, contrast, desaturation, and vibrancy applied to the blurred background.
- Color tint overlay — Configurable color tint.
- Fresnel edge glow — Schlick-based fresnel approximation at the glass edge.
- Specular highlight + inner shadow — Top-biased highlight and bottom-rim shadow for depth.
For windows, the plugin integrates with Hyprland's render pass system as a DECORATION_LAYER_BOTTOM decoration, drawing before the window surface so the glass shows through transparent windows. For layer surfaces, the plugin hooks renderLayer and uses a temp FBO redirect: the background is sampled and blurred, then Hyprland's surface rendering is redirected into a transparent temporary framebuffer to capture the surface's exact alpha. A post-surface pass then composites the glass effect (masked to visible content only) and the surface content back onto the main framebuffer in a single shader pass.
hyprctl plugin unload /path/to/hyprglass.so- The plugin requires Hyprland shadows to be present in the render pipeline. It auto-enables them at load time if disabled — shadow visual values (range, color…) can be zero, only the decoration's presence matters.
- Layer surface glass uses a function hook on
renderLayer, which is a private Hyprland internal. The hook may break on Hyprland updates that change this function's signature.
See repository for license details.

