[Unity×Gaussian-Splatting]GSをVFX Graphで動かしてみた

## 初めに
今回、株式会社GENEROSITY様でインターンシップをさせていただき、その中で行った開発について記事を書いていきます！
他にもいくつか記事を書いたので、他の記事も見ていただけると嬉しいです！
## 本記事を読む前に
この記事では、Unityのインストールなどについては記述しません。インストールが終わっている前提で進めていきます。インストールについては下記のリンクから行ってください。

https://unity.com/ja/download

Unityの基本的な操作については省略して解説を進めていきます。わからないところがあるときは適宜調べながら進んでください。

## 本記事で出来ること
このデモを動かすことができる

https://x.com/_kzr/status/1714214841265856932?s=20

パーティクルから風景に戻すという表現ができる
![gs03.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2517131/0827d219-54b8-5c0c-c08b-ee09b7e579dc.gif)



# 目次

[1.Gaussian-Splattingとは](#gaussian-splattingとは)
[2.事前準備](#事前準備)
[3.デモを動かす](#デモを動かす)
　[1.モデルのインポート](#モデルのインポート)
　[2.VFXを動かす](#vfxを動かす)
[4.改造](#改造)
　[1.Initialize Particle](#initialize-particle)
　[2.Update Particle](#update-particle)
　[3.Output Particle](#output-particle)
[5.実行](#実行)
[6.まとめ](#まとめ)
[7.参考資料](#参考資料)

## Gaussian-Splattingとは
複数の写真から3Dのシーンを再構成する技術のことです。
似たような技術で`NeRF`という技術もあるのですが、それとは別の技術になります。

https://note.com/npaka/n/ncd4b84c1e2eb

https://zenn.dev/aster_ideatech/articles/523b4909d4e48f

## 事前準備
今回、下記のGitHubのデモを動かしていくのですが、このプロジェクトを作成したUnityバージョンが2023.1.16f1なので、このバージョンのUnityをインストールしてください。

:::note warn
2021、2022でも動作はすると思いますが、予期せぬエラーに遭遇する可能性があるので、今回は2023を使用します。
:::

https://github.com/keijiro/SplatVFX/tree/main

## デモを動かす
GitHubからプロジェクトを持ってきて、それをUnityで開いてください。いくつかのフォルダが含まれていますが、`VFX`という名前のフォルダを開いてください。

![gs01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2517131/94e57867-ee2d-bf28-0149-cbfddd93908b.png)

Unityが開けたら、Assetsフォルダに含まれる`VFX`というSceneを開いてください。

### モデルのインポート
Sceneが開くことができたら、Gaussian Splattingのモデルをインポートします。
先ほどのGitHubに`bicycle.splat`のモデルをダウンロードできるリンクがあるので、こちらからダウンロードします。

![gs02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2517131/733887dc-0bcc-af69-0f64-966eb4c0d1ef.png)

ダウンロードができたら、Unityのインポートします。

### VFXを動かす
デモ動画のように動かすためのセットアップをします。
HierarchyにあるVFXというオブジェクトを選択し、そのオブジェクトに付いている`VFX Property Binder`のProperty Bindingsをクリックします。
その中の`Splat Data`の部分に先ほどインポートしたGaussian Splattingのモデルをアタッチします。

![gs03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2517131/cad5eb49-1008-0444-3737-39f933a5e8e4.png)

アタッチができると緑に変わるので、そうしたら実行します。

![gs04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2517131/408c20b2-687a-6bbb-2962-b8bb949074b5.png)

デモと同じような動画が流れると思います。

![gs.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2517131/290d22f1-08cd-3df8-0708-038b1e2c436f.gif)

## 改造
パーティクルから風景に戻すという表現を実装したいと思います。
VFXファイルをコピーして、もう一つ作っておきます。そのコピーしたファイルを開いてください。

![gs05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2517131/bb471c45-811d-cae2-b3c6-9891eeb10a36.png)

### Initialize Particle

パーティクルが動いている状態から、最終的にとある指定の位置に移動する必要があるため、`TargetPosition`を決める必要があります。
TargetPositionを決めるためのオペレーターが存在しないので、そのためのSubgraph Operatorを作成します。このオペレーターの内部は、`Initialize Splat`の内容をオペレーターに直したものになります。
AssetsにSubgraph Operatorを作成し開きます。そして、下記の内容を作成してください。

![gs07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2517131/963f606d-e467-1c55-e1c1-5d83121c2169.png)

Initialize Particleの内部を変更します。
先ほど作成したオペレーターを配置し、オペレーターのPositionを`Set Target Position`につなげます。
ここで`LifeTime`も適当な数字にしておきます。ランダムにすると、最後に風景に戻す際、パーティクルの寿命が終えてしまってその部分の風景が欠損するかもしれないので、おすすめはしません。
パーティクルの初期位置を決めるために`Set Position`を行います。今回は、AABoxを選択しましたがお好みで大丈夫です。

![gs08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2517131/a09a9ed8-e880-76e1-b69e-44197ca0ca6d.png)

### Update Particle
続いて、Update Particleの内部を変更していきます。一度、中のノードをすべて消します。
`Add Position`を追加してください。このノードを利用して、だんだんTarget Positionに近づくという処理を行います。

![gs09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2517131/65ef7b69-0ff1-f3df-06a5-c55611cdf602.png)

:::note info
今回、Turbulenceも追加しています。これはお好みで追加してください。内容としては、最初はパーティクルが動き回ってだんだんその動きをなくしていくといったような内容になっています。
:::

### Output Particle
ここでは、少しだけ変更をします。
Output Particle Unlit Quad内の`Multiply Size Over Life`を0からスタートして、途中で1になるように変更します。
次に、Output Particle Quadの`Set Size`を`Set Size Over Life`に変更し、0.01くらいから0になるようにします。

![gs11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2517131/d064ef4f-1988-6b52-77d5-e930fe3a63fd.png)


ここまで実装をしたら、保存を行い、Visual Effect コンポーネントのAsset Templateを作成したVFX Graphに変更してください。

![gs10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2517131/9d1b61ee-244d-e5d3-f7a5-216c92ccf996.png)

## 実行
パーティクルから風景が作られるような表現になったと思います。

![gs03.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2517131/0827d219-54b8-5c0c-c08b-ee09b7e579dc.gif)

## まとめ
Gaussian SplattingでVFX Graphを使った表現ができました。ノードを組み替えることで、いろいろな表現ができるので試してみたいと思っています！

## 参考資料

https://github.com/keijiro/SplatVFX/tree/main

https://docs.unity3d.com/Packages/com.unity.visualeffectgraph@12.0/manual/index.html

https://edom18.hateblo.jp/entry/2021/01/08/081203