
目次
- はじめに
- 検証環境
- UI Toolkit における UIEffect の選択肢
- ShaderGraph 経路
- Filter 経路
- 応用 1:RenderTexture で背景エフェクト UI
- 応用 2:親要素 Filter で Text + Image をまとめて PostEffect
- おわりに
- 関連リンク
はじめに
Unity 6.3 で UI Toolkit にグラフィックス系のアップデートが入りました。 ShaderGraph を VisualElement に適用したり、Filter 機能で描画結果全体にエフェクトをかけたりできます。 この新機能を活かして UI Toolkit でどこまでリッチな表現を組めるか、ShaderGraph と Filter の 2 経路で体系化しました。

検証環境
- Unity Editor:
6000.4.6f1 - Render Pipeline: URP
17.4.0 - Shader Graph:
17.4.0
UI Toolkit における UIEffect の選択肢
UI Toolkit のエフェクト表現は2種類の方法が考えられます。
以下の表にまとめました。
| 経路 | 適用方法 | 強み | 弱み |
|---|---|---|---|
| ShaderGraph (Material) | USS の Material で Material を差し替え |
ノードベースで色変換系を直感的に組める / 描画前の Color/Alpha を直接いじれる | 単一描画 (1 つの VisualElement) にしか掛からない |
| USS Filter | USS の filter プロパティで指定。Custom Filter も組める |
親要素にかけると配下がまとめてエフェクト処理される / Custom Filter で任意の shader 効果を組める | Custom Filter は shader を自作する手間がかかる |
使い分けの軸は、エフェクトを掛けたい対象が 1 つの VisualElement か、複数の VisualElement かという点です。 単一なら ShaderGraph、複数をまとめて掛けたいなら Filter、という整理で使用しています。 同じ見た目のエフェクトでも、用途に応じて両方の経路で実装することがあります。
ShaderGraph 経路
まず簡単にですが、UI Toolkit で ShaderGraph を使用する設定手順を説明していきます。
Project以下で右クリックをしてCreate/ShaderGraph/URP/UI Shader Graphを選択して生成します。

ShaderGraph実装
ここからは今回表現したShaderGraphのエフェクトについて詳しく見ていきます。 今回のShaderGraphでは下記の画像を元画像(MainTex)として使用しています。

各エフェクトのShaderGraphの中身は以下の通りです。
Tone: Grayscale (彩度を 0 にして白黒化)

Tone: Sepia (Sepia 行列で茶色調)

Tone: Negative (1 - color で反転)

ColorMode: Multiply (TintColor を乗算合成)

ColorMode: Add (AdditiveColor を加算合成)

装飾: Shiny (光のラインが走る)

装飾: Gradient (UV ベースのグラデーション)

統合 ShaderGraph (SubGraph + Keyword でまとめる)
各エフェクトは SubGraph として独立して作成しました。SubGraph 化することで、エフェクトを 1 つの親 ShaderGraph に集約し、Boolean Keyword と Branch ノードで動的に切り替えられる構成にしています。
7 つの SubGraph を直列に並べ、Grayscale → Sepia → Negative → Multiply → Add → Shiny → Gradient こちらの順序で描画処理していきます。
各段の出力を Boolean Keyword Branch ノードで「Keyword ON ならエフェクト適用後、Keyword OFF なら前段の値」と切り替え、最終結果を Fragment.BaseColor に渡します。
_TONE_GRAYSCALE_ON や _SHINY_ON などの Keyword を Material 側でトグルするだけで、任意のエフェクトを任意の組み合わせで適用できます。

UI Toolkit で ShaderGraph の適用
作成したShaderGraphは、UIBuilder上で対象のUXMLを開き各要素ごとに設定していくことでMaterial(ShaderGraph)の設定ができます。

Filter 経路
Filter機能についても設定方法から説明していきます。
Filterの設定方法は、対象UXMLをUI Builder上で開き、対象要素のInlined Styles/Filterから対象のエフェクトを選択するだけです。

Filter機能にはデフォルトですでにいくつかの機能があります(USS Filter 公式ドキュメント)。今回は Custom Filter の実装について紹介していきます。
Custom Filter実装
まず、シェーダー(.shader)を書きます。 全てエフェクトを紹介してしまうと長くなってしまうので、今回は色収差について紹介していきます。
Shader "UI/Filters/ChromaticAberration" { Properties { _MainTex ("Texture", 2D) = "white" {} _Strength ("Strength (UV)", Range(0.0, 0.1)) = 0.025 _Angle ("Angle (deg)", Float) = 0 } SubShader { Tags { "RenderType"="Transparent" "Queue"="Transparent" "RenderPipeline"="UniversalPipeline" } Cull Off ZWrite Off ZTest Always Blend SrcAlpha OneMinusSrcAlpha Pass { HLSLPROGRAM #pragma vertex vert #pragma fragment frag #pragma multi_compile _ UIE_OUTPUT_LINEAR #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" struct appdata { float4 positionOS : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 positionCS : SV_POSITION; }; TEXTURE2D(_MainTex); SAMPLER(sampler_MainTex); float4 _MainTex_TexelSize; // _Strength: 0=ズレなし、大きいほど色チャネル分離が強い (UV 単位) // _Angle : 色ズレの方向 (degrees)。R/B を逆方向にずらす軸を制御する float _Strength; float _Angle; v2f vert(appdata v) { v2f o; o.positionCS = TransformObjectToHClip(v.positionOS.xyz); o.uv = v.uv; return o; } half4 frag(v2f i) : SV_Target { float angleRad = _Angle * 0.01745329; // deg → rad float2 axis = float2(cos(angleRad), sin(angleRad)); float2 offset = axis * _Strength; // R は +方向、B は -方向、G は中心。古典的な色ズレ手法。 float2 uvR = i.uv + offset; float2 uvG = i.uv; float2 uvB = i.uv - offset; // 範囲外サンプリングを抑えるため境界クランプ uvR = clamp(uvR, _MainTex_TexelSize.xy * 0.5, 1.0 - _MainTex_TexelSize.xy * 0.5); uvG = clamp(uvG, _MainTex_TexelSize.xy * 0.5, 1.0 - _MainTex_TexelSize.xy * 0.5); uvB = clamp(uvB, _MainTex_TexelSize.xy * 0.5, 1.0 - _MainTex_TexelSize.xy * 0.5); half r = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uvR).r; half4 g4 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uvG); half b = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uvB).b; // UIToolkit用 Gammaに変換処理 #ifdef UIE_OUTPUT_LINEAR col.rgb = GammaToLinearSpace(col.rgb); #endif half4 col = half4(r, g4.g, b, g4.a); return col; } ENDHLSL } } }
.shaderができましたら次に、FilterFunctionDefinition アセットを作成します。
こちらも作成方法は簡単で、Project以下で右クリックし、Create → UI Toolkit → Filter Function Definition を選択します。

生成されたFilterFunctionDefinitionアセットに今回は「ChromaticAberrationFilter」と名前をつけて、下記画像の通りInspector上で設定します。

設定のポイントは以下の3つです。
Filter Name: USS から参照する際の識別子(chromaticAberrationなど)Parameters: USS で引数として渡せるパラメータの順序(strength,angle)とデフォルト値Passes: 実際に走らせる Material(先ほど作成した shader を割り当てた.mat)と、shader プロパティへのバインド(_Strength← parameter[0]、_Angle← parameter[1])
最後にUIBuilder上からVisualElementに追加していきます。
Inlined Styles/Filter内の「+」ボタンを押して、Customを選択します。
その後、Definitionの参照を上で作ったchromaticAberrationのDefinitionに設定し、strengthとangleに値を入れます。

これでCustomFilterの作成と適用は完了です。
応用 1:RenderTexture で背景エフェクト UI
ゲーム開発をしているとポーズ画面やダイアログなどを表示する際に背景に対してブラーをかけて表示したいということがあると思います。 そのような演出を UI Toolkit で行う場合どのように実装していくのか紹介していきます。

実装の選択肢
UI 側に RenderTexture を表示するには、いくつかの実装方法があります。今回は構成がシンプルになるよう、事前に RenderTexture を用意して専用カメラから書き込む実装にしました。
専用カメラから RenderTexture へ書き出す
BackgroundCamera という名前で 3D シーン撮影用の Camera を1つ追加します。Inspector の Output Texture(= targetTexture)には、事前に用意した RenderTexture アセットを割り当てます。
RenderTexture は次のような構成にしています。
Size: UI 表示サイズに合わせる(本記事のサンプルでは 512×288)Depth Stencil Format:D32_SFloat_S8_UInt(Stencil を使う Filter にも対応できるよう 8bit Stencil 付き)Color Format:R8G8B8A8_UNorm

VisualElement に RenderTexture を流し込む
VisualElement に背景画像として RenderTexture を流すには、style.backgroundImage に Background.FromRenderTexture(rt) を渡します。USS では RenderTexture を直接 background-image に指定できないので、C# 側で実行時にバインドします。
using UnityEngine;
using UnityEngine.UIElements;
public class RenderTextureUIBinder : MonoBehaviour
{
[SerializeField] UIDocument uiDocument;
[SerializeField] RenderTexture renderTexture;
[SerializeField] string[] targetElementNames;
// rootVisualElement は Awake / OnEnable では未生成のことがあるため、Start と OnEnable 両方から BindAll を呼ぶ。
void Start() => BindAll();
void OnEnable() => BindAll();
void BindAll()
{
// rootVisualElement が未生成のフレームでは何もせず、後続の Start / OnEnable 呼び出しで再試行する。
if (uiDocument == null || uiDocument.rootVisualElement == null || renderTexture == null) return;
if (targetElementNames == null) return;
// RenderTexture は USS から直接指定できないため、Background.FromRenderTexture + StyleBackground で C# から流し込む。
var background = new StyleBackground(Background.FromRenderTexture(renderTexture));
foreach (var name in targetElementNames)
{
// UI Toolkit の VisualElement ツリーは UQuery(.Q<T>(name))で目的の要素を取得する。
var element = uiDocument.rootVisualElement.Q<VisualElement>(name);
if (element != null)
{
element.style.backgroundImage = background;
}
}
}
}
Inspectorの設定内容は以下の通りです。

ここまで設定したら、その VisualElement に対して USS の Material で ShaderGraph の Material を割り当てたり、filter: filter(url(...)) で Custom Filter を適用したりできます。RenderTexture の中身にエフェクトが掛かった状態で表示可能です。
「3D シーン → RenderTexture」へ書き出した時点で、それ以降は通常の UI 画像と同じ扱いになるので、ここまでに紹介した ShaderGraph 系・Filter 系のエフェクトがそのまま使えるようになります。
ポーズ画面で「背景の 3D だけブラー、UI は素」のように見せたい場合は、UI を写さない専用カメラから RT に書き出し、filter: blur(8px) を適用した VisualElement の背景として表示するだけで実現できます。
応用 2:親要素 Filter で Text + Image をまとめて PostEffect
ゲーム開発をしていると動的に変更されるTextとTextに合わせた背景Imageに対してエフェクトを掛けたいというケースもよくあると思います。 UI Toolkit でこの表現を実装する方法を紹介します。

UXML 構造
各UIをまとめて表示構成する UXML は次のような階層になります。親のVisualElementに対して filter を指定することで、配下の Label(Score 等)と VisualElement(アイコン画像)と背景がまとめて 1 パスで PostEffect されます。
parent ← この要素に filter: filter(url("ChromaticAberrationFilter.asset")) を指定
├── title (Label: "ChromaticAberration")
├── icon (VisualElement: 背景画像)
├── score-label (Label: "Score: 12,345" 動的更新)
└── caption (Label: "HIGH SCORE")
UI Builder 上の設定はこのようになります。

これで parent を含む配下のラスタライズ結果が 1 枚のテンポラリ RT に書き込まれ、それに対して ChromaticAberrationFilter が 1 回だけ走るという挙動になります。
uGUI 時代の UI Effect との比較
uGUI 時代にリッチな UI エフェクトを実装する場合、BaseMeshEffect や独自シェーダーを各要素に貼り付ける方式が一般的でした。
今回 UI Toolkit で実装してきた内容を、この旧来手法と並べて整理してみます。
| 比較項目 | uGUI 時代 (旧来) | UI Toolkit (今回) |
|---|---|---|
| エフェクトの記述場所 | コンポーネント (C#) に集約 | ShaderGraph・USS Filter・USS に分散できる |
| 適用単位 | Image / Text 個別に貼り付け | 親 VisualElement にまとめて指定可能 |
| 多重がけ | コンポーネントを多段に重ねる | filter: blur(4px) filter(url(...)) で USS だけでエフェクトを重ねられる |
| デザイナーとの分業 | C# 改修が必要なことが多い | 見た目の調整を USS 側に寄せやすい |
| メッシュ加工系の自由度 | 頂点単位で細かく操作できる | 現状は ShaderGraph / Filter の範囲が中心 |
たとえば「動的なテキストと背景画像にブラーを掛けたい」「ダイアログ全体に色収差を掛けたい」といった要件は、uGUI 時代には各要素を CanvasGroup で囲んだり、RenderTexture 経由で組んだりと、それなりの作業量が必要でした。UI Toolkit の Filter なら親要素に設定するだけで配下をまとめて処理してくれるため、こうしたケースの記述量を大幅に抑えられます。 このように、描画前の色変換や全体への PostEffect といった用途では、UI Toolkit のほうが宣言的に組めるようになりました。一方、頂点を直接いじるような細かいメッシュ加工は、まだ uGUI 側に分があるケースもあります。
おわりに
今回の追加により、よりリッチな表現が UI Toolkit で実装できるようになりました。 これによってランタイムで UI Toolkit が導入されるプロジェクトも増えてくると考えています。 とはいえ、まだ行えないことも多いと思いますので、今後のアップデートにも期待が高まります。
関連リンク
- UI Toolkit
- ShaderGraph (UI Shader Graph)
- VisualElement
- Boolean Keyword (Shader Graph)
- USS Filter functions
- Custom Filter
- FilterFunctionDefinition
- BaseMeshEffect (uGUI)



