【Godot】ガウスブラーの実装方法

# 概要
この記事ではGodot Engineでのガウスブラーの実装方法について紹介します。


# ブラーを適用するプロジェクトの作成
## 画像の設定
今回のブラーは画面全体に適用するため、シーン内のノードの並び順に依存する方法です。
![Godot_Engine_-_TestBlur_-_Main_tscn____.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/24a5d1b4-2513-9c1e-6275-95f89dc615d9.png)
そのルールを理解するため、2つの画像を用意します。

まずは背景画像。(→ "bg.jpeg" として保存）
![bg.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/29cd5f18-e335-7fef-94cd-ad6534cc6853.jpeg)
次にスクリプトで動かすオブジェクト画像 (→ "tako.png" として保存)
![tako.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/1c2d718a-27c5-3790-480f-f21695f7212b.png)
この2つの画像をプロジェクトに登録しておきます。

## ウィンドウサイズの変更
今回は画像サイズに合わせて 480x320 の解像度にするため、`プロジェクト > プロジェクト設定` を開き、`Display > Window` で 480 x 320 に変更しておきます。
![Godot_Engine_-_TestBlur_-_Main_tscn.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/09138092-a57d-db00-1afe-1d93fa7b1821.png)

## 画像の配置
2Dシーン(Node2D)として、Mainノードを作成し、"bg.jpeg" と "ch.png" をドラッグ＆ドロップで配置します。
![Godot_Engine_-_TestBlur_-_Main_tscn____.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/c79e060e-979e-8123-5aa6-f89d06f656e6.png)
![Godot_Engine_-_TestBlur_-_Main_tscn____.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/2488e530-8d0c-8ee3-9c04-f3a08c638359.png)

## オブジェクトを動かす
chにスクリプトをアタッチして、以下のように記述します。

```gd:ch.gd
extends Node2D

var velocity = Vector2(200, 100)

func _ready():
	pass

func _process(delta):
	position += velocity * delta
	if position.x < 0:
		position.x = 0
		velocity.x *= -1
	if position.y < 0:
		position.y = 0
		velocity.y *= -1
	if position.x > 480:
		position.x = 480
		velocity.x *= -1
	if position.y > 320:
		position.y = 320
		velocity.y *= -1
```

実行するとたこ焼きが画面内をバウンドして動き回ります。
![shot.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/905b0972-b899-1275-178a-4bcf086fc5dc.gif)

## ブラーシェーダーの追加
"bg.jpeg" をドラッグ＆ドロップして、シーンノードの最後に追加します。
![Godot_Engine_-_TestBlur_-_Main_tscn.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/f072ec1a-1772-73cb-2f5e-0efb88747164.png)
ノードの名前を "blur" に変更しておきます。
なお、ここでは背景画像を登録しましたが、画面サイズのテクスチャが必要なだけなので、適用したい範囲に合わせて好きな画像を使うことができます。

"blur"ノードを選択して、インスペクタから `CanvasItem > Material > Material > [空]` をクリックして、「新規ShaderMaterial」を選択します。
![Godot_Engine_-_TestBlur_-_Main_tscn_____と_イラスト2___512_x_512px_72dpi_100_0__.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/4146b356-9ec4-03c8-fb14-c47f6bf93e76.png)
少し下にスクロールして、`Shader > [空]` をクリックして「新規 Shader」を選択します。
![Godot_Engine_-_TestBlur_-_Main_tscn____.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/88ebc766-a694-7822-0ac6-dcb6d8147f52.png)
すると、エディタの中央下にシェーダーコードエディタが表示されます。
![Godot_Engine_-_TestBlur_-_Main_tscn____.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/3570de86-53a8-2998-c582-f9746a49d66a.png)

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

```glsl
shader_type canvas_item;

// ブラーの強さ.
uniform float blur_amount = 3.0;

void fragment() {
	// スクリーンテクスチャにガウスぼかしをかける
	COLOR = textureLod(SCREEN_TEXTURE, SCREEN_UV, blur_amount);
}
```

すると "blur" スプライトの範囲にブラーが適用されます。
![Godot_Engine_-_TestBlur_-_Main_tscn.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/61e1ce49-5c31-5788-2bfc-39a4bc2fd537.png)

実行してブラーが適用されていることを確認します。
![shot.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/c31584c3-7084-aff7-77e2-4a795ee934ee.gif)

なお、このブラーは画面全体に適用しているので、ノードの順番を入れ替えることで適用されるノードを変えることができます。
![shot.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/1bc5067a-ed68-69eb-9c1e-3afabb517e46.gif)

## エディタからブラーの強さを変えられるようにする
"blur" ノードにスクリプトをアタッチして、ブラーの値をエディタから変更できるようにします。

```gd:blur.gd
tool
extends Sprite

export(float, 0.0, 5.0) var blur_amount

func _process(delta: float) -> void:
	material.set_shader_param("blur_amount", blur_amount)

```

`tool` 宣言は シーンの読み直しが必要なので、Mainシーンを保存後いったん閉じて、開き直します。
そして "blur" ノードを選択すると、インスペクタからブラーの強さをリアルタイムで設定できます。

![shot.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/0f77c4b3-282d-37f6-d7a2-0d8fb8e0ae63.gif)

# 追記 (2021.2.20)：WorldEnvironmentでブラーをかける
シェーダーを書かなくても `WorldEnvironment` を使うことで画面全体にぼかしを書けることができるようです。
まずは `WorldEnvironment`を作成して……
![Godot_Engine_-_TestHDR_-_Main_tscn____.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/edc2bbbd-cd6e-7531-024a-5da29bf21c7e.png)
インスペクタから「新規 Environment」を追加します。
![Godot_Engine_-_TestHDR_-_Main_tscn____.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/2bd7cff4-eac3-2dc0-f1fb-112c7ebf279d.png)
作成した　Environmentの `Background > Mode` を「Canvas」に変更
![Godot_Engine_-_TestHDR_-_Main_tscn____.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/c4270327-ce34-d111-b365-d76a1309a250.png)
`Dof Near Blur > Enable`を有効にするとブラーが画面全体にかかります。
![shot.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/756be7fc-4991-c93f-b41f-3f9db9dc141c.gif)
ブラーの強さは「Amount」の値で調整できます。

ちなみに「Dof」というのは「Depth of Field(被写界深度)」のことで、例えば背景画像にはぼかしをかけることで前面にいるキャラクターに注目させる手法となります。

# 参考

* [Godot Docs » シェーディング » スクリーン読み取りシェーダー](https://docs.godotengine.org/ja/stable/tutorials/shading/screen-reading_shaders.html)
* [Blur shader :: Godot Recipes](https://kidscancode.org/godot_recipes/shaders/blur/)