# Glur: Metal-backed progressive blur modifier for SwiftUI

> Glur is a Swift package that adds a progressive blur modifier to SwiftUI views using Metal shaders. It ships two products: the main Glur modifier with no private API, and GlurBackdrop which reaches private API to blur content behind a view.

**joogps/Glur** — A library for progressive blurs in SwiftUI.

- Repository: https://github.com/joogps/Glur
- Stars: 2,075 · Forks: 45
- Language: Swift
- License: MIT
- Published: 2026-10-11 · Updated: 2026-10-11 · Language: en
- Canonical page: https://hysenlabs.com/projects/joogps-glur

## Progressive blur using Metal, without CIFilter or private API in the main module

Apple's UI applies progressive blur throughout its own interfaces: content fades into blur at an edge rather than disappearing behind a sharp line. Reproducing that in SwiftUI previously meant CIFilter, which adds processing overhead, or reaching into private APIs. Glur adds a .glur() SwiftUI view modifier that uses Metal shaders for the same result, and the main Glur product carries no private API.

What makes a blur progressive is that the blur radius varies across the view. A flat blur applies one radius to every pixel. A progressive blur drives the radius from zero at one side to maximum at another, producing the smooth fade that Apple's design uses across iOS and macOS.

Glur ships as a Swift package. It lists iOS 15.0, macOS 12.0, watchOS 8.0, tvOS 15.0 and visionOS 1.0 as its minimum platform versions in the README badges.

## Two products split the functionality along the private-API boundary

Two products split the library along the private-API line. The Glur product provides the .glur() modifier and GlurMask. It operates on the SwiftUI-rendered view it is applied to, which limits it to content the framework draws itself, and it uses no private API. The GlurBackdrop product provides GlurView, a transparent overlay that blurs whatever is rendered behind it, covering ScrollView and other platform-backed views.

Mask definitions are shared between both products because GlurBackdrop depends on Glur, so the same GlurMask types work with .glur() and GlurView. Neither product enters a binary unless it is explicitly linked as a target dependency. That linkage boundary is what lets developers use the main modifier without the private-API exposure that comes with GlurBackdrop.

## Adding Glur via Xcode and writing the first .glur() modifier call

Glur is a Swift package. Add it through Xcode at File > Add package dependencies, select the repository, and choose which product to link. After linking, bring the package into scope:

```swift
import Glur
```

The modifier call at its simplest takes no arguments:

```swift
.glur()
```

All six parameters are optional. The full call from the README shows each one with its default:

```swift
.glur(radius: 8.0,
      offset: 0.3,
      interpolation: 0.4,
      direction: .down,
      noise: 0.1,
      drawingGroup: true
)
```

Radius sets the maximum blur applied at full intensity. Offset determines where the effect begins as a fraction of the view's size from the relevant edge, and interpolation sets how far the ramp takes to reach full strength, also as a fraction of the view's size. The noise parameter adds a texture to the blur. Setting drawingGroup to true pre-renders the modified view through SwiftUI's drawingGroup().

## GlurMask encodes blur as opacity; linear, radial, view and image shapes are available

GlurMask represents blur intensity as opacity: zero opacity on the mask leaves a pixel untouched and full opacity applies the blur at maximum radius. The shorthand parameters on .glur() are shorthand for the default linear mask, so these two calls produce identical results:

```swift
.glur(radius: 8.0, offset: 0.3, interpolation: 0.4, direction: .down)
.glur(radius: 8.0, mask: .linear(direction: .down, offset: 0.3, interpolation: 0.4))
```

Passing a mask directly gives access to shapes the shorthand cannot represent. A radial mask concentrates the unblurred area in the center and blurs toward the corners:

```swift
.glur(radius: 8.0, mask: .radial(offset: 0.2, interpolation: 0.5))
.glur(radius: 8.0, mask: .radial(offset: 0.2, interpolation: 0.5, spread: 2.5))
```

The spread parameter on a radial mask controls how far the ramp extends as a multiple of the view's longest side. A value above 1.0 pushes the outer edge of the ramp beyond the view's boundary, so the corners never reach the maximum radius.

The .view() type accepts any SwiftUI view as a mask: angular gradients, shapes, text and images are all valid. Colors in any mask are discarded; only opacity determines the blur intensity. Built-in masks are drawn once and cached. A .view() mask cannot be cached that way because it may change, so it redraws on every update to the effect.

## Three functional tiers: compatibility on iOS 15, GlurView on iOS 16, Metal on iOS 17

Platform support has more layers than the badge list in the README header shows. Glur's stated minimum is iOS 15.0, but the Metal implementation only activates on iOS 17.0, macOS 14.0 and tvOS 17.0. Below those versions but above the package minimum, Glur runs a fallback that the README describes as producing a worse effect, and it advises the developer to test it before production use.

GlurView has a higher minimum than the .glur() modifier. It starts at iOS 16.0, macOS 13.0 and tvOS 16.0 because it rasterizes masks through ImageRenderer, an API introduced in that release cycle. The .glur() modifier's Metal path starts a full version later, at iOS 17.0, and its compatibility fallback never uses ImageRenderer at all.

This creates three distinct tiers: iOS 15 receives the compatibility effect only; iOS 16 adds GlurView as an option; iOS 17 activates the Metal path in the main modifier. WatchOS sits outside this progression entirely. The Metal implementation is not available on watchOS, so the compatibility effect runs on every watchOS version, and GlurView renders as empty space on that platform.

## GlurBackdrop reaches a private API; the README states the App Store risk without softening it

No public Apple API applies a varying blur to a backdrop. GlurBackdrop works by looking up class names at runtime, stored as code units rather than readable string literals so that no plaintext API reference appears in the binary. The README addresses this directly: 'that is obfuscation rather than a guarantee.' The risk statement ends with: 'Weigh the App Store risk yourself before shipping it.'

The separate module is the architectural response to that risk. Linking the Glur product alone exposes no private API. GlurBackdrop enters a target only through an explicit product linkage, so the two products can coexist in a codebase without every target taking on the private-API exposure.

MacOS behavior for GlurView has additional caveats. The README begins to address this but the available repository text trails off before completing that note, so the full extent of macOS-specific behavior for GlurView is not recorded in the documentation captured here.

## Shader effects disappear above 545 points in the iOS simulator; v2.0 ships on 2026-08-10

One limitation specific to the iOS simulator: SwiftUI shader effects may not display when the view exceeds 545 points in either dimension. The README confirms the effect works correctly on physical devices, which makes the simulator an unreliable test environment for any view that fills a full-width phone layout or an iPad canvas at all. Testing at large view sizes requires a physical device.

v2.0 was released on 2026-08-10 and v1.1 on 2025-10-09. The repository carries the MIT licence.

## Conclusion

Glur suits SwiftUI projects that want the progressive blur pattern Apple applies throughout its own UI, without CIFilter or private API in the main module. Anyone evaluating GlurBackdrop for backdrop blur should read the private API section of the README, weigh the App Store submission risk, and test on every platform they target, since watchOS renders GlurView as empty space. On iOS 15 or 16, the compatibility effect replaces Metal, so test the visual result on older devices before shipping. The 545-point simulator limit makes physical device testing the only reliable way to verify the effect at large view sizes.

## FAQ

### What is Glur?

Glur is a Swift package that adds a progressive blur modifier to SwiftUI using Metal shaders. It varies the blur radius across a view according to a grayscale mask and requires no CIFilter in its main product.

### Does Glur use private APIs?

The main Glur product uses no private APIs. The GlurBackdrop product, which blurs content behind a view, uses private API accessed by class name at runtime. The README warns about App Store risk and advises weighing it before shipping.

### What iOS version does Glur require for the Metal blur?

The Metal implementation requires iOS 17.0 or later. On iOS 15 and 16, Glur uses a fallback that the README describes as producing a worse effect. GlurView also requires iOS 16.0 as a minimum because it depends on ImageRenderer.

### How do I add Glur to an Xcode project?

Use File > Add package dependencies in Xcode and add the repository URL. Select either the Glur product for the modifier alone, or GlurBackdrop to also include the backdrop blur view. Then import Glur or import GlurBackdrop in the Swift files that use it.

### Does Glur work on watchOS?

Glur lists watchOS 8.0 as a supported minimum, but Metal is not available for this effect on watchOS. The compatibility effect runs instead, and GlurView renders as empty space on watchOS.

## Sources

- [Issues](https://github.com/joogps/Glur/issues)
- [joogps/Glur on GitHub](https://github.com/joogps/Glur)
- [License: MIT](https://github.com/joogps/Glur/blob/main/LICENSE)
- [README](https://github.com/joogps/Glur/blob/main/README.md)
- [Releases](https://github.com/joogps/Glur/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/joogps-glur
