【Godot】2Dモーションブラーの実装方法

# 概要
この記事では、Godot Engineでの2Dモーションブラーの実装方法を紹介します。
モーションブラーとは特定の方向への移動が高速であるかのように見せる映像演出となります。
![shot.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/4f5d28dd-a814-cbc8-3044-77225c3ac0d8.gif)
カメラがブレるような動きなので、この画像のような動きであれば、画面揺れの演出として使うこともできます。

今回の記事は以下の動画を参考（というかほぼそのまま）にしました。

* [2D Motion Blur Shader in the Godot Engine](https://www.youtube.com/watch?v=qDT-nJXmfL0)

# モーションブラーの実装

## 画像素材
モーションブラーを適用する画像として以下の素材を使用します。名前を "bg.png" として保存します。
![bg.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/8488f51a-d50d-563b-10ba-f50029371958.png)

## ノイズテクスチャのダウンロード
下記URLからノイズテクスチャをダウンロードします。
https://drive.google.com/drive/folders/1uMfCOLoPEyH5St06pWmOReYPSb7-hP72

"BlurNoise.png" を右クリックして「ダウンロード」でダウンロードできます。
![Directional_Blur_-_Google_ドライブ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/24465f82-f41c-e6a0-6480-3b4ada8cc1c3.png)

## 画像を登録
プロジェクトを作成し、"bg.png" と "BlurNoise.png" をプロジェクトに追加します。
そして、"bg.png" をドラッグ＆ドロップで配置します。
![Godot_Engine_-_TestShockWave____.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/d81c2946-c542-bd14-1a9c-4030563b5a47.png)

## シェーダーの作成
bgノード (`Sprite`) のインスペクタから、`CanvasItem > Material > Material > [空]` をクリックして、「新規 Shader Material」を選びます。
![Godot_Engine_-_TestShockWave_-_Main_tscn.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/ed11c496-75fb-1cff-d30e-ca249a936998.png)
作成した Shader Materialをクリックして、`Shader > [空]` をクリック、「新規 Shader」を選びます。
![Godot_Engine_-_TestShockWave_-_Main_tscn____.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/279ce0b1-b3de-d25f-7182-27e970520f04.png)
作成した Shaderをクリックすると、シェーダーエディタが表示されます。
![Godot_Engine_-_TestShockWave_-_Main_tscn____.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/2bc6e018-d91d-0820-e63d-4b1d16c7fee8.png)

## シェーダーコードの記述
シェーダーコードは以下のように記述します。

```glsl
shader_type canvas_item;

render_mode blend_mix;

uniform float     angle_degrees : hint_range(0.0, 360.0)       = 0.0; // ブラーの方向(角度)
uniform float     strength      : hint_range(0.0, 1.0, 0.0001) = 0.0; // ブラーの強さ
uniform int       samples       : hint_range(2, 32, 2)         = 8;   // サンプル数。2の倍数でないとダメ //MUST BE A MULTIPLE OF 2
uniform sampler2D noise; // ノイズテクスチャ

// Directional Blur Shader
// Adapted from https://www.shadertoy.com/view/ldBXWG
vec4 DirectionalBlur(in vec2 uv, in vec2 MotionVector, in sampler2D Texture) {
	// 黒色で初期化
	vec4 Color = vec4(0.0);
	float Noise = texture(noise,uv * 20.0).x - 0.485;

	for (int i = 0; i < samples / 2; i++) {
		// 両側に書き込む
		// 右側
		Color += texture(Texture,uv + (float(i+1) * MotionVector ) /float(samples/2) * Noise * 2.0);
		// 左側
		Color += texture(Texture,uv - (float(i+1) * MotionVector ) /float(samples/2) * Noise * 2.0);
	}
	
	// サンプルの数だけ色を薄くする
	return Color / (float(samples));
}

void fragment() {
	// 方向を計算
	vec2 blur_vector = vec2(cos(radians(angle_degrees)), sin(radians(angle_degrees))) * strength;
	
	// ブラーの色を計算
	COLOR = DirectionalBlur(UV, blur_vector * strength, TEXTURE);
}
```

次にこのシェーダにノイズテクスチャを適用します。

`CanvasItem > Shader > Shader Param > Noise > [空]` をクリックして、「読込み」を選びます。
![Banners_and_Alerts.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/293133ac-3e42-2f68-6c76-bb45bda152d4.png)

"BlurNoise.png" を選んで「開く」をクリックします。
![Godot_Engine_-_TestMotionBlur_-_Main_tscn____.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/c2c0c31c-2b0f-5494-4759-bf41cfb4946c.png)

すると `Noise` にノイズテクスチャが設定されました。
![Banners_and_Alerts.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/fe29856f-aece-33cb-e383-3333a8779925.png)

## 動作確認
`Shader Param > Strength` の値を変化させてモーションブラーの効果を確認します。

![shot.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/4f5d28dd-a814-cbc8-3044-77225c3ac0d8.gif)

# ぼかしの品質を上げる
ノイズテクスチャによるぼかしは処理が高速なぶん、あまりキレイなぼかしではないので、もう少し品質を上げたい場合は、`WorldEnvironment` を使用します。
![Godot_Engine_-_TestMotionBlur_-_Main_tscn____.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/f738b186-e469-ddb9-c6bd-02a7e6cb45fc.png)

そして、Environmentを新規作成して、`Environment > Background > Mode` を「Canvas」に設定し……
![Banners_and_Alerts.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/cbcd6cd9-395b-b619-c4f4-425d19f161ed.png)

`Dof Near Blur > Enabled` をオンにすると品質の良いぼかし処理が適用されます。（強さは「Amount」で調整）
![Banners_and_Alerts.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/8f96a934-49e4-7990-aa62-69b3f58c2518.png)
ただ、おそらくこちらの方が重たい処理であるので適切に使う必要があるのと、モーションブラーの強さのパラメータに合わせてこちらの「Amount」の値も調整する、などの処理が必要となります。

# プロジェクトファイル
今回作成したプロジェクトファイルは以下からダウンロードできます。
http://syun777.sakura.ne.jp/tmp/godot/TestMotionBlur.zip

# 参考

* [2D Motion Blur Shader in the Godot Engine](https://www.youtube.com/watch?v=qDT-nJXmfL0)