【Godot】ブルームを適用する方法

# 概要
この記事では、Godot Engine でブルームを適用する方法について書きます。
ブルームとは以下のように、明るい部分を広げて明るい部分を強調しつつも、ぼやっと明るくなるので、何となく高級感が出ます。
![shot.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/79641131-a6c5-85cc-5f8b-ccf0266356bf.gif)
ただ、常時適用する場合は強くかけすぎるとゲームプレイを阻害するので、目立たせたいオブジェクトのみに適用するか、うっすらと適用するのが使い道としてはよさそうです。

# ブルームの実装
## 画像の登録
今回の素材として以下の画像を使用します。名前を "bg.png" として保存します。
![bg.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/314e0ea0-f027-d9fd-f727-e1bd56492fb0.png)

## 画像の配置
シーンを作成して画像を配置します。
場所はどこでも問題ありません。


## WorldEnvironmentの追加
次に `WorldEnvironment`を追加します。
![Godot_Engine_-_TestHDR_-_Main_tscn____.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/c3ce5f54-fb22-3d32-09a8-0e8cf809d17e.png)

この`WorldEnvironment`さんはかなり優秀で以下の機能を持っています。

* **Depth of Field Blur** :被写界深度＝ぼかし
* **Glow** :輝度調整
* **Tonemap (Auto Exposure)**:トーンマップ（自動露出）
* **Adjustments** :調整

例えば、"Depth of Field Blur" はぼかしを簡単に実装できます。また "Adjustments" では輝度調整、コントラスト、彩度の調整ができます。
下のGIF動画は、`Adjustments > Saturation` による彩度調整です。グレースケール(灰色にする）や彩度を高くしてビビットな色使いにしたりできます。
![shot.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/f452c60a-1747-4fd6-f7e4-c1df8430b176.gif)

## Environmentの追加
`WorldEnvironment`を追加した状態だと以下のような警告が表示されています。
![Godot_Engine_-_TestHDR_-_Main_tscn____.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/9e116e20-0f76-f62d-211f-89ea5ac4a86a.png)

これは `Environment`が追加されていないためです。
インスペクタから`Environment`を追加します。
手順としては、`WorldEnvironment > Environment > [空]` をクリックして「新規 Environment」を選択します。
![Godot_Engine_-_TestHDR_-_Main_tscn____.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/eb60e8de-afdd-46b3-9f6d-af31fe5b9a24.png)

`Environment > Background > Mode` を「Canvas」に変更します。
![Godot_Engine_-_TestHDR_-_Main_tscn____.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/2fbf9c6b-6d51-ae15-cc4e-7e17f2e8c7ba.png)

そして、`Glow > Enabled` にチェックを入れると、`Glow > Bloom` の値を変化せることでブルームをかけることができます。
![shot.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/58e69a5a-21c3-83bd-60a7-2501381ee049.gif)

ブルームのかかり方が弱いなぁ……と思ったら `Glow > Blend Mode` を 「Softlight(弱いライト)」から「Addictive(加算)」にすると強めにブルームが適用されます。
![Godot_Engine_-_TestHDR_-_Main_tscn____.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/e4bb218b-4edf-d0c4-37d9-509b0e261e2b.png)
![shot.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/79641131-a6c5-85cc-5f8b-ccf0266356bf.gif)

# シェーダーで実装する
公式のサンプルを見ていたらシェーダーでのグローの実装例があったので合わせて紹介しておきます。

* [godotengine/godot-demo-projects: Demonstration and Template Projects](https://github.com/godotengine/godot-demo-projects)

![shot.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/2287567f-e289-b758-8e6c-bc89fbf81ca9.gif)



```glsl
shader_type canvas_item;
render_mode blend_premul_alpha;

uniform float radius : hint_range(2, 5);
uniform float amount : hint_range(0, 5);
 
void fragment() {
	float r = radius;
	vec2 ps = TEXTURE_PIXEL_SIZE;
	vec4 col = texture(TEXTURE, UV);
	vec4 glow = col;

	glow += texture(TEXTURE, UV + vec2(-r, -r) * ps);
	glow += texture(TEXTURE, UV + vec2(-r, 0.0) * ps);
	glow += texture(TEXTURE, UV + vec2(-r, r) * ps);
	glow += texture(TEXTURE, UV + vec2(0.0, -r) * ps);
	glow += texture(TEXTURE, UV + vec2(0.0, r) * ps);
	glow += texture(TEXTURE, UV + vec2(r, -r) * ps);
	glow += texture(TEXTURE, UV + vec2(r, 0.0) * ps);
	glow += texture(TEXTURE, UV + vec2(r, r) * ps);

	r *= 2.0;
	glow += texture(TEXTURE, UV + vec2(-r, -r) * ps);
	glow += texture(TEXTURE, UV + vec2(-r, 0.0) * ps);
	glow += texture(TEXTURE, UV + vec2(-r, r) * ps);
	glow += texture(TEXTURE, UV + vec2(0.0, -r) * ps);
	glow += texture(TEXTURE, UV + vec2(0.0, r) * ps);
	glow += texture(TEXTURE, UV + vec2(r, -r) * ps);
	glow += texture(TEXTURE, UV + vec2(r, 0.0) * ps);
	glow += texture(TEXTURE, UV + vec2(r, r) * ps);

	glow /= 17.0;
	glow *= amount;
	col.rgb *= col.a;

	COLOR = glow + col;
}
```

# 参考

* [Godot Docs » Godot API » Environment](https://docs.godotengine.org/ja/stable/classes/class_environment.html#class-environment)