UI blur for HDRP

A real-time Kawase dual-filter blur for Unity UI, rendered as an HDRP Custom Pass.

on this page

com.bluecadet.uiblur-hdrp renders the same Kawase dual-filter blur as the URP package, integrated into the High Definition Render Pipeline through UIBlurCustomPass, a CustomPass added to a Custom Pass Volume. The implementation lives in one file, Scripts/UIBlurCustomPass.cs (namespace Bluecadet.UIBlur.HDRP).

Requirements

  • Unity 6000.3+
  • High Definition Render Pipeline (HDRP)
HEADS UP

package.json declares no dependency on HDRP. If HDRP isn’t installed in the consuming project, this package won’t compile.

Install

OpenUPM is the recommended path:

sh
openupm add com.bluecadet.uiblur-hdrp

The scoped registry (https://package.openupm.com, scope com.bluecadet) only needs adding once per project.

To install from a Git URL instead, point at the release tag, which follows the com.bluecadet.uiblur-hdrp@<version> format:

json
{
  "dependencies": {
    "com.bluecadet.uiblur-hdrp": "https://github.com/bluecadet/unity-packages.git?path=Packages/com.bluecadet.uiblur-hdrp#com.bluecadet.uiblur-hdrp@<version>"
  }
}

Pick a version from Releases — every released tag is listed there. The openupm add form above always takes the latest.

Setup

  1. Create an empty GameObject in your scene.
  2. Add Component > Rendering > Custom Pass Volume.
  3. Set its injection point to your preferred timing.
  4. Click + and select UIBlurCustomPass.
  5. Configure the settings below.

UIBlurCustomPass is [System.Serializable], but its Setup, Cleanup, and Execute overrides are all protected — there’s no public API beyond the three serialized fields below, and nothing to call from script.

Settings

FieldRangeDefaultDescription
blurScale0–2564Blur intensity. Higher values produce stronger blur.
renderTextureNamestring_UIBlurTextureName of the global render texture that UI shaders sample.
resolutionScale0.25–1.00.5Render resolution multiplier, used as-is with no further clamping.

Unlike the URP inspector, these fields render without group headers — the [Header(...)] attributes in source are commented out.

NOTE

There’s no “Blur Passes” inspector setting. Pass count is computed at render time from blurScale via a private ComputeBlurParams, capped internally at 12 passes — it isn’t user-configurable.

Sample in a UI shader

hlsl
TEXTURE2D_X(_UIBlurTexture);
SAMPLER(sampler_UIBlurTexture);

half4 frag(Varyings i) : SV_Target {
    float2 screenUV = i.screenPos.xy / i.screenPos.w;
    half4 blurColor = SAMPLE_TEXTURE2D_X(_UIBlurTexture, sampler_UIBlurTexture, screenUV);
    return blurColor * _Color;
}

For the Kawase dual-filter algorithm itself, see the URP package.

Shaders

AssetShader name
Shaders/KawaseDualFilter.shaderBluecadet/UIBlur/KawaseDualFilterHDRP
Shaders/UIBlur.shaderBluecadet/UIBlur/UIBlurHDRP

URP vs. HDRP

URPHDRP
IntegrationUIBlurRenderFeature on a URP Renderer assetUIBlurCustomPass inside a Custom Pass Volume
Pass timingSerialized renderPassEvent, default AfterRenderingTransparentsThe Custom Pass Volume’s injection point — no field on the pass itself
Settings shapeSeparate BlurSettings class, plus a BlurScale passthrough propertyThree fields directly on the pass, no property wrappers
Internal pass capMAX_PASSES = 6MAX_PASSES = 12
Resolution clampSetup re-clamps resolutionScale to 0.1–1Uses resolutionScale as-is
Render pathRender Graph (Blitter.BlitTexture)RTHandle arrays + CoreUtils.DrawFullScreen
Blur shaderBluecadet/UIBlur/KawaseDualFilterBluecadet/UIBlur/KawaseDualFilterHDRP
Example UI shaderBluecadet/UIBlur/UIBlurBluecadet/UIBlur/UIBlurHDRP

The pipelines also differ internally: HDRP skips the render-graph abstraction in favor of manually pre-allocated RTHandle arrays (RTHandles.Alloc) drawn with CoreUtils.DrawFullScreen / CoreUtils.SetRenderTarget; its shaders use SAMPLE_TEXTURE2D_X/TEXTURE2D_X for XR single-pass and a manual UV Y-flip via UNITY_UV_STARTS_AT_TOP, and carry a "RenderPipeline" = "HDRenderPipeline" tag. In the Scene view (CameraType.SceneView), HDRP clears its final render target to Color.clear and sets that as the global texture, where URP swaps in a black texture instead.