Documentation

// URP UI Blur Pro · v1.0.0 · Unity 6 / URP 17+

How It Works

URP UI Blur Pro integrates with URP's rendering pipeline, captures the scene at a configurable point, runs a blur algorithm, and makes the result available for UI panels and 3D world objects to sample. The blur computes once per profile per frame — panels themselves do no blur work at draw time.

The blur only runs when at least one active BlurImage or BlurObject references that profile. Profiles with no active consumers cost nothing.

01
Scene renders normally

Geometry, skybox, and transparents render through URP as usual.

02
Background is captured

The Blur Renderer Feature captures the rendered scene at the point controlled by each profile's CaptureMode.

03
Blur passes run on the GPU

The captured image is processed by the selected algorithm. Up to 16 profiles can run simultaneously, each fully independent.

04
Panels sample the result

BlurImage (UI panels) and BlurObject (3D meshes) sample the blurred output and apply frost tint, brightness, desaturation, and optional normal-map distortion.

Requirements

RequirementVersion
Unity6000.0 or later
Universal Render Pipeline17.0.0 or later
RenderGraphEnabled in Project Settings → Graphics → URP Global Settings
PlatformsPC, Mobile — VR/XR not tested, not officially supported

Quick Start

01Open the Setup Wizard via Tools → URPUIBlur → Setup Wizard. It also opens automatically on first import.
02Tick the URP Renderer assets you want to add the feature to, then click Add Blur Feature.
03Add a UI Image component to your Canvas and add a BlurImage component to the same GameObject.
04Assign a BlurProfile asset to the Profile field, or click New to create one inline.
05Set Capture ModeWithout Post Processing works with all Canvas modes and is the recommended default.
06Press Play. The blur is active immediately.

Capture Mode

CaptureMode controls which point in URP's frame the background is captured at.

CaptureModeRender EventNotes
WithoutPostProcessing BeforeRenderingTransparents Compatible with all Canvas modes and BlurObject. Use in most cases.
WithPostProcessing AfterRenderingPostProcessing Includes bloom, tonemapping, color grading. Screen Space Overlay only — using this with Screen Space Camera or World Space produces a black panel.
Both branches simultaneously: a single profile can serve WithoutPostProcessing and WithPostProcessing at the same time for different BlurImage components with no conflict — each branch is an independent pass-chain with its own RTHandles.

Blur Methods

MethodCostBest For
Dual Kawase●●○○○Frosted-glass UI — widest radius at lowest cost
Custom Kawase●●○○○Fast circular blur with tunable tap count
Poisson Disk●●●○○Cinematic bokeh — eliminates grid sampling artifacts
Gaussian Separable●●●○○Mathematically exact Gaussian circle
Tent / Hex●●●●●Hexagonal lens bokeh — cinematic moments
Radial●●○○○Zoom blur, impact effects, cutscenes

BlurProfile

A BlurProfile is a serializable asset describing how to blur — algorithm, pass count, and per-algorithm parameters. It contains no appearance settings; those live on the BlurImage or BlurObject that references it. Up to 16 profiles can be active simultaneously.

Create a profile: Assets → Create → URPUIBlurPro → Blur Profile, or click New next to the Profile field on any BlurImage component.

Common parameters

PropertyTypeRangeDescription
blurMethodBlurMethodAlgorithm used for this profile
intensityfloat0–1Blur strength multiplier. 0 = no blur, 1 = full authored strength. Scales parameters each frame without modifying serialized values. Shared across all BlurImages referencing this profile.
iterationsint1–8Pass count / mip pyramid depth — more = wider blur
blurOffsetfloat0–5Tap spread multiplier (scales with screen resolution)
downsampleint1–8RT resolution divisor — auto-adjusted for screens wider than 1920 px

Dual Kawase

Uses iterations and blurOffset. The mip pyramid is built automatically; no additional parameters needed.

Custom Kawase / Poisson Disk

PropertyRangeDescription
taps3–12Number of samples per pass
useIGNRotationbool(Poisson only) Per-pixel sincos rotation — higher quality, minimal cost

Gaussian Separable / Tent Hex

PropertyRangeDescription
gaussianRadius1–16Sample radius in pixels (scales with screen resolution, capped at 64)

Radial

PropertyRangeDescription
radialTaps4–32Number of samples arranged around the ring
radialRadius0.5–20Ring radius in texels (scales with screen resolution)

Update Mode

Controls how often the blur pass chain re-runs. Skipped frames reuse the last blurred result at zero added cost.

PropertyTypeDescription
updateModeBlurUpdateModeEveryFrame (default) or Throttled
throttleFpsint 0–120Max blur updates per second in Throttled mode. 0 = freeze: blurs once on activation, holds that frame, re-captures each time the panel reopens.
ModeUse Case
EveryFrameLive-moving content — game world, animated backgrounds
Throttled (1–120)Semi-static UI over a mostly-still background. May ghost on fast motion.
Throttled (0, freeze)Fully static backgrounds — pause menus, modals. Near-zero cost after first frame.

BlurImage Component

BlurImage attaches a profile's blur output to a UI Graphic (Image, RawImage, etc.). It creates and manages a private Material instance using UI_Blur_Universal, enabling the correct slot keyword and syncing appearance lazily via a dirty flag.

Settings

FieldTypeDescription
profileBlurProfileThe blur recipe to sample. Supports up to 16 profiles simultaneously.
captureModeCaptureModeWhether to include post-processing in the blur (see Capture Mode).
frostTintColorColor tinted over the blurred background.
frostStrengthfloat 0–1Tint blend weight (0 = no tint, 1 = full tint).
brightnessfloat 0.8–1.5Brightness multiplier applied after tint.
desaturatefloat 0–1Desaturation amount (0 = full color, 1 = grayscale).
edgeStrengthfloat 0.5–1Vignette darkening toward panel edges (1 = no vignette).
tintColorColorOverall tint multiplied with vertex color.
normalMapTextureNormal map driving glass surface distortion.
bumpStrengthfloat 0–1Distortion intensity.
normalMapTilingVector2Tiling of the normal map texture.
normalMapOffsetVector2Offset of the normal map texture.
normalModeNormalModeUV calculation mode for the normal map (see below).

Normal Mode

ValueDescription
StandardTileUses the Image's own UV directly.
LocalFixedScaleScales with screen resolution — resolution-independent (default).
ScreenSpaceFixProjected in screen space, aspect-corrected.

Public API

BlurImage API
// Force appearance fields to push into the material on the next Canvas repaint.
// Call this after changing appearance fields from script.
blurImage.MarkDirty();

// Animate profile.intensity from its current value to 1 over `duration` seconds.
// Reverses smoothly if called while a FadeOut is in progress.
// Uses unscaled time -- works during Time.timeScale = 0.
blurImage.FadeIn(0.4f);

// Animate profile.intensity from its current value to 0, then stop.
blurImage.FadeOut(0.4f);
Shared profile note: FadeIn and FadeOut animate profile.intensity, which is per-profile. If multiple BlurImage components share the same profile, all of them fade together. Use a dedicated profile per panel to fade them independently.

BlurObject Component

BlurObject attaches a profile's blur output to a MeshRenderer (windows, floors, glass panels in 3D space). It always uses WithoutPostProcessing capture — 3D transparent objects render during the transparent pass, so capturing any later would include the object's own draw call and produce a black surface.

Settings

FieldTypeDescription
profileBlurProfileThe blur profile to sample.
frostTintColorColor tinted over the blurred background.
frostStrengthfloat 0–1Tint blend weight.
brightnessfloat 0.8–1.5Brightness multiplier applied after tint.
desaturatefloat 0–1Desaturation amount.
refractionIndexfloat 0–0.5IOR offset — how strongly the surface bends the background sample.
normalMapTextureSurface detail driving refraction direction.
bumpStrengthfloat 0–1Refraction bend intensity.
tintColorColorOverall tint multiplied with vertex color.
mainTexTextureAlbedo texture blended over the blur result. Leave empty for plain frosted glass.

Modifying Parameters at Runtime

All fields on a BlurProfile can be written at runtime. Changes take effect on the next rendered frame.

RuntimeParameters.cs
BlurProfile p = myBlurProfile;

// Continuous -- takes effect next frame, zero overhead
p.blurOffset     = 2f;   // Dual Kawase / Kawase / Poisson tap spread
p.gaussianRadius = 8;    // Gaussian / Tent-Hex pixel radius
p.radialRadius   = 6f;   // Radial ring radius in texels

// Discrete -- takes effect next frame, no pass rebuild
p.iterations = 4;
p.taps       = 8;
p.downsample = 2;
p.radialTaps = 16;

// Method -- triggers pass rebuild on next frame
// May produce a one-frame hitch on mobile. Change during loading screens.
p.blurMethod = BlurMethod.GaussianSeparable;

After changing appearance fields on BlurImage or BlurObject from script, call MarkDirty() to push the changes to the material:

AppearanceRuntime.cs
blurImage.frostTint     = new Color(0.8f, 0.9f, 1f, 1f);
blurImage.frostStrength = 0.5f;
blurImage.brightness    = 1.1f;
blurImage.MarkDirty();

Intensity & Fade

profile.intensity scales all blur-strength parameters each frame without modifying the serialized values. Unlike toggling isActive, intensity 0 keeps the pass alive so there is no one-frame black flash when the blur returns.

ScaledNot Scaled
blurOffset, gaussianRadius, radialRadius, iterations, downsample blurMethod, taps, radialTaps, useIGNRotation
IntensityAPI.cs
// Set directly
myProfile.intensity = 0.5f;

// Or via the typed API
myProfile.SetIntensity(0.5f);
float current = myProfile.GetIntensity();

// Built-in coroutine fade on BlurImage
blurImage.FadeIn(0.4f);   // current -> 1 over 0.4s, unscaled time
blurImage.FadeOut(0.3f);  // current -> 0 over 0.3s, unscaled time
Shared profile note: intensity is per-profile, not per-BlurImage. Multiple BlurImage components sharing the same profile are all affected simultaneously. Use a dedicated profile per panel to control them independently.

Update Mode

Use updateMode and throttleFps to reduce how often the blur pass re-runs. Skipped frames reuse the persistent RTHandle untouched — zero added cost beyond the BlurImage's own sample.

UpdateModeAPI.cs
// Throttle to 30 blur updates/sec
myProfile.updateMode  = BlurUpdateMode.Throttled;
myProfile.throttleFps = 30;

// Freeze: blur once on activation, hold until panel closes and reopens
myProfile.updateMode  = BlurUpdateMode.Throttled;
myProfile.throttleFps = 0;

// Return to every-frame blur
myProfile.updateMode = BlurUpdateMode.EveryFrame;

Common Patterns

Pause menu with blur fade

PauseMenu.cs
[SerializeField] BlurImage _blurImage;

void OpenMenu()
{
    gameObject.SetActive(true);
    _blurImage.FadeIn(0.4f);
    Time.timeScale = 0f;
}

void CloseMenu()
{
    _blurImage.FadeOut(0.3f);
    Time.timeScale = 1f;
}

Manual intensity animation

ManualFade.cs
[SerializeField] BlurProfile _profile;
float _target;

void Update()
{
    float current = _profile.GetIntensity();
    _profile.SetIntensity(Mathf.MoveTowards(current, _target, Time.deltaTime * 4f));
}

void OnMenuOpen()  => _target = 1f;
void OnMenuClose() => _target = 0f;

Quality preset switching

Switch algorithm and parameters during scene load to match player graphics settings.

QualityManager.cs
[SerializeField] BlurProfile _profile;

void ApplyQuality(int level)
{
    switch (level)
    {
        case 0: // Low
            _profile.blurMethod = BlurMethod.DualKawase;
            _profile.iterations = 2;
            _profile.downsample = 4;
            break;
        case 1: // Medium
            _profile.blurMethod = BlurMethod.DualKawase;
            _profile.iterations = 3;
            _profile.downsample = 2;
            break;
        case 2: // High
            _profile.blurMethod = BlurMethod.PoissonDisk;
            _profile.iterations = 4;
            _profile.downsample = 2;
            break;
    }
}

Battery saver mode

Disable all BlurImage components to stop the blur from running entirely.

PowerManager.cs
BlurImage[] _allImages;

void Awake()
{
    _allImages = FindObjectsByType<BlurImage>(
        FindObjectsInactive.Include, FindObjectsSortMode.None);
}

void SetBatterySaver(bool enabled)
{
    foreach (var img in _allImages)
        img.enabled = !enabled;
}

Known Limitations

These are by-design constraints from how URP's RenderGraph schedules render passes. They are not bugs.

3D objects may not appear inside the blur

WithoutPostProcessing captures at BeforeRenderingTransparents. Any 3D object that hasn't rendered yet at that point is entirely absent from the captured texture.

Workaround: use WithPostProcessing on a Screen Space Overlay canvas — it captures after all geometry has finished rendering.

World Space canvas panels are always occluded by Screen Space Camera canvases

Unity draws Screen Space Camera canvases on top of World Space canvases regardless of scene hierarchy. Additionally, the two canvas modes capture at different stages, so neither blur can see the other's panel content.

There is no workaround for this combination. Change the Screen Space Camera canvas to Screen Space Overlay instead — Overlay always renders after World Space geometry, so layering and blur capture both work correctly.

Blur panels rendered by the same camera cannot see each other's blur output

When two BlurImage panels are rendered by the same camera, both capture at BeforeRenderingTransparents — the same moment in the same frame. The front panel's blur runs before the back panel has been composited into the color buffer, so it samples the raw scene rather than the already-blurred backdrop.

Screen Space Overlay: no workaround. All Overlay canvases render through the same implicit camera and share the same capture point.

Workaround — separate canvases on separate cameras via Camera Stack: place each panel on its own Screen Space Camera canvas, each assigned to a different camera. Stack the cameras so the popup camera renders after the backdrop camera. The popup's BlurImage then captures a color buffer that already contains the backdrop blur.

  1. Keep your Main Camera with Culling Mask set to Everything.
  2. Add a second camera. Set Render Type to Overlay and Culling Mask to UI only. Match projection, FOV, and clipping planes to the Main Camera.
  3. Make the new camera a child of the Main Camera and zero its local position and rotation.
  4. In the Main Camera's Camera Stack, add the new camera as the last entry.
  5. Set the backdrop canvas to Screen Space Camera, Render Camera = Main Camera.
  6. Set the popup canvas to Screen Space Camera, Render Camera = Stack Camera.

Both canvases must use Screen Space Camera mode — placing both panels on the same canvas or the same camera will not work even with a Camera Stack. Use a separate BlurProfile per panel to control each independently.

Screen Space Overlay blurs everything

Overlay + WithPostProcessing captures after all geometry — opaque, transparent, world-space, and 3D objects — and includes post-processing effects. It is the most reliable option when you need the blur to include all scene content.

Troubleshooting

UI panel is black / shows no blur

• Confirm the Blur Renderer Feature is added and enabled on the active URP Renderer asset.

• Ensure a BlurProfile is assigned to the BlurImage component.

• If using WithPostProcessing, confirm the Canvas is set to Screen Space Overlay.

Blur appears pixelated or blocky

• Reduce downsample — high values produce a low-resolution RT that becomes visible at low blur strength or when intensity is below 1.

• Increase iterations or blurOffset to widen the blur and soften the pixelation.

Blur stops updating / freezes unexpectedly

• Check updateMode on the profile — Throttled with throttleFps = 0 intentionally freezes the blur after the first frame.

• Confirm at least one BlurImage referencing the profile is enabled and visible — profiles with no active consumers stop running automatically.

Normal map shows dark fringe / black edges at high bump strength

• The distortion UV is sampling outside the blur RT's scissor region. The scissor automatically expands by bumpStrength to cover the distortion range — confirm bumpStrength is not larger than the panel's screen-space margin allows.

• Move the panel away from screen edges, or reduce bumpStrength.

Performance is poor

• Switch to Dual Kawase (lowest cost per quality).

• Increase downsample to 4 and reduce iterations to 2.

• See Performance Tips below for profiling-level optimisations.

Setup Wizard shows no renderers

• Open it manually via Tools → URPUIBlur → Setup Wizard.

• If no renderers appear, create a URP Universal Renderer asset first: Assets → Create → Rendering → URP Universal Renderer.

BlurImage looks correct in Scene view but wrong in Game view

• The Scene view camera is separate from the Game camera and may capture at a different resolution or with different post-processing. Always treat Game view as the reference.

• If the Scene view blur looks distorted, this is expected — the scissor rect is computed from the Game camera's viewport, not the Scene camera's.

Performance Tips

These optimisations apply to any platform, not just mobile. Each active profile runs its full pass chain every frame it is needed — reducing what runs and how often has the most impact.

Share one profile across multiple BlurImages

If multiple panels need identical blur parameters, assign them the same BlurProfile. The pass chain runs once and all panels sample the same result — zero additional GPU cost per extra panel.

Use Update Mode to reduce how often the blur re-runs

Set updateMode to Throttled for panels over a mostly-still background. Skipped frames reuse the last blurred result at zero added cost.

Set throttleFps to 0 to freeze the blur after its first frame — ideal for pause menus, modals, and any background that does not move while the panel is open.

Assign the same CaptureMode to all BlurImages on a profile

Each distinct CaptureMode branch (WithoutPostProcessing / WithPostProcessing) is a separate pass chain with its own RTHandles. Mixing capture modes on the same profile doubles the GPU and memory cost for that profile.

Keep the active profile count low

Each active profile is an independent pass chain. Consolidate panels that share parameters into fewer profiles rather than giving every panel its own profile.

Disable BlurImage components when not visible

A profile's pass chain stops running automatically when all its BlurImage consumers are disabled or invisible. Disable the component (not just the GameObject's alpha) when a panel is fully hidden to eliminate its cost entirely.

Third-Party Credits

Dual Kawase Blur — algorithm by Marius Bjørge, presented at GDC 2015 (ARM).