UI blur for HDRP
A real-time Kawase dual-filter blur for Unity UI, rendered as an HDRP Custom Pass.
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)
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:
openupm add com.bluecadet.uiblur-hdrpThe 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:
{
"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
- Create an empty GameObject in your scene.
- Add Component > Rendering > Custom Pass Volume.
- Set its injection point to your preferred timing.
- Click + and select UIBlurCustomPass.
- 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
| Field | Range | Default | Description |
|---|---|---|---|
blurScale | 0–256 | 4 | Blur intensity. Higher values produce stronger blur. |
renderTextureName | string | _UIBlurTexture | Name of the global render texture that UI shaders sample. |
resolutionScale | 0.25–1.0 | 0.5 | Render 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.
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
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
| Asset | Shader name |
|---|---|
Shaders/KawaseDualFilter.shader | Bluecadet/UIBlur/KawaseDualFilterHDRP |
Shaders/UIBlur.shader | Bluecadet/UIBlur/UIBlurHDRP |
URP vs. HDRP
| URP | HDRP | |
|---|---|---|
| Integration | UIBlurRenderFeature on a URP Renderer asset | UIBlurCustomPass inside a Custom Pass Volume |
| Pass timing | Serialized renderPassEvent, default AfterRenderingTransparents | The Custom Pass Volume’s injection point — no field on the pass itself |
| Settings shape | Separate BlurSettings class, plus a BlurScale passthrough property | Three fields directly on the pass, no property wrappers |
| Internal pass cap | MAX_PASSES = 6 | MAX_PASSES = 12 |
| Resolution clamp | Setup re-clamps resolutionScale to 0.1–1 | Uses resolutionScale as-is |
| Render path | Render Graph (Blitter.BlitTexture) | RTHandle arrays + CoreUtils.DrawFullScreen |
| Blur shader | Bluecadet/UIBlur/KawaseDualFilter | Bluecadet/UIBlur/KawaseDualFilterHDRP |
| Example UI shader | Bluecadet/UIBlur/UIBlur | Bluecadet/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.