[Unity uGUI] ブラーシェーダー(Blur Shader)。
画像をブレさせる処理。
関連ページ
シェーダー処理の中でも一般的な部類のBlurシェーダーを作ってみました。画像をブレさせ、ぼやけさせる処理です。

Blurシェーダー概要
下がブラーシェーダーを効果を撮った動画です。
プロパティの
BlurCount
がBlurを掛ける回数、
BlurDistance
がBlurの制度になります。
BlurCountは、1上げる度に爆発的にBlurのサンプリング回数が上がっていきます。
たとえばこのシェーダーで設定している最大値の20を指定すると、(20x2+1)の2乗で画像1ピクセルにつき1681回テクスチャを読み込みます。
画像のぼやけ具合を調整する際は、BlurCountは適度に抑えて、なるべくBlurDistanceで調整する方法をお勧めします。

コード全文
以下シェーダーのコード全文です。uGUI Imageへの反映方法は
こちらの記事
参照してください。
基礎知識として次の記事にも目を通すと分かり易いです。
p.57 : シェーダー基礎、最もシンプルなuGUI用 URP Shader

Shader
"UI/BoxBlur"
{
Properties
{
[HideInInspector]_MainTex("-",2D)="white"{}
_BlurCount("Blur
Count",
Range(0,
20))
=
1
//何回Blur処理を繰り返すか
_BlurDistance("Blur
Distance",
Range(1,
10))
=
1
//Blurの際、何ピクセルずれた場所からピクセル色を抜き出すか
}
SubShader
{
Tags
{
"Queue"
=
"Transparent"
}
Cull
Off
ZWrite
Off
Blend
SrcAlpha
OneMinusSrcAlpha
HLSLINCLUDE
#pragma
vertex
vert
#pragma
fragment
frag
#include
"Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
//uGUI Image > Source Imageにアタッチされた画像を参照できるようにする
TEXTURE2D(_MainTex);
SAMPLER(sampler_MainTex);
//Source Imageにアタッチされた画像のピクセルサイズを参照できるようにする
float4
_MainTex_TexelSize;
//SRP Batcherを適用
CBUFFER_START(UnityPerMaterial)
//今回追加したプロパティに対応する変数
int
_BlurCount;
half
_BlurDistance;
CBUFFER_END
struct
Attributes
{
half2
uv
:
TEXCOORD0;
float4
positionOS
:
POSITION;
half4
color
:
COLOR;
};
struct
Varyings
{
half2
uv
:
TEXCOORD0;
float4
positionCS
:
SV_POSITION;
half4
color
:
COLOR;
};
Varyings
vert
(Attributes
input)
{
Varyings
output;
output.positionCS
=
TransformObjectToHClip(input.positionOS.xyz);
output.uv
=
input.uv;
output.color
=
input.color;
return
output;
}
ENDHLSL
Pass
{
HLSLPROGRAM
half4
frag
(Varyings
input)
:
SV_Target
{
//Source Imageにアタッチされた画像の縦横ピクセルサイズに対し、その逆数を取得
//x: 1/width(ピクセル幅の逆数)
//y: 1/height(ピクセル高さの逆数)
//z: width(ピクセル幅そのもの)
//w: height(ピクセル高さそのもの)
half2
texelSize
=
_MainTex_TexelSize.xy;
half4
color
=
0;
int
count
=
0;
for
(int
x
=
-_BlurCount;
x
<=
_BlurCount;
x++)
{
for
(int
y
=
-_BlurCount;
y
<=
_BlurCount;
y++)
{
//x軸、y軸に対しuv座標をいくらずらすか取得
half2
offset
=
half2(x
*
_BlurDistance,
y
*
_BlurDistance)
*
texelSize;
//inputから渡されたuv座標に、offsetの修正値を与えて指定画像からピクセル色を取得してcolorに色を加算
color
+=
SAMPLE_TEXTURE2D(_MainTex,
sampler_MainTex,
input.uv
+
offset);
count++;
}
}
//加算した回数分だけ割って平均色を出す
return
color
/
count;
}
ENDHLSL
}
}
}


コード解説
コードの中でいまいち分かり辛い部分は、
_MainTex_TexelSize.xy
という画像サイズの逆数を計算に使っている部分になります。
//Source Imageにアタッチされた画像の縦横ピクセルサイズに対し、その逆数を取得
//x: 1/width(ピクセル幅の逆数)
//y: 1/height(ピクセル高さの逆数)
//z: width(ピクセル幅そのもの)
//w: height(ピクセル高さそのもの)
half2
texelSize
=
_MainTex_TexelSize.xy;
逆数を使っているのは、シェーダーのuv座標というものが、0~1の間に値が正規化されているためです。
5x5ピクセルの極小の画像があるとして、そのuv座標は1 / 5 = 0.2ずつ、紐づくピクセルが移動していきます。
左端のピクセルはx = 0~0.2の範囲、右端のピクセルは0.8~1の範囲です。
500x500ピクセルの場合、そのuv座標は1 / 500 = 0.002ずつ移動していきます。
左端のピクセルはx = 0~0.002の範囲、右端のピクセルは0.008~1の範囲です。
画像サイズは大きく違いますが、uv座標は変わらず0~1の範囲です。
_BlurCount = 1の時、for文を見るとx軸y軸ともに3回ずつBlur処理を行っています。
for
(int
x
=
-_BlurCount;
x
<=
_BlurCount;
x++)
{
for
(int
y
=
-_BlurCount;
y
<=
_BlurCount;
y++)
{
//x軸、y軸に対しuv座標をいくらずらすか取得
half2
offset
=
half2(x
*
_BlurDistance,
y
*
_BlurDistance)
*
texelSize;
xもyも-1, 0, 1のいずれかの値で、(x = 0, y = 0)は座標をずらさないオリジナルの画像です。
そしてtexelSizeは1ピクセル分の座標の移動値を表します。
つまり_BlurDistance = 1だとした場合、上下左右に1ピクセルだけブレさせて重ねる処理という事が分かります。
0
0