UnrealEngineで全天球(360度)画像を撮影してファイルに保存する

いつの間にかUnrealEngineのScneneCaptureComponentCubeでFinal Colorが使えるようになっていて、ポストプロセスが適用された全天球(360度)画像をキャプチャできるようになっていました。
いままでだと、以下のサイトのようにレンダリング用のスクリーンと2Dキャプチャが必要だったのですが、もっとシンプルに撮影できるようになってますね。

[[UE4] Unreal Engine 4.22 で360°動画(パノラマ静止画）を簡単に作ってみよう！！ |](https://www.wanimation2910.com/2019/04/15/360pano/)

実際に全天球(360度)画像撮影をやってみた内容をまとめておきます。

# 確認環境

UE4.27.2
UE5.1.0

# 撮影方法
## RenderTargetCubeの用意

Content Browserで右クリックし[Materials & Textures] > [Cube Render Target]から以下のようなRenderTargetCubeを用意します。

![RenderTargetCube_2022-08-05 114920.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16768/962d0207-7da7-6837-8aa0-987d1beb05b5.png)

### Target Gammaの値について

以下の記事を参考にしてTarget Gammaを設定しています。
2.2という値にしないと出力される画像が暗くなります。

[[UE4]インゲーム画像キャプチャに便利なノード「Export to Disk」の紹介｜株式会社ヒストリア](https://historia.co.jp/archives/16883/)
>TextureRenderTarget2Dでは通常のプレイヤーカメラにかかっているUE4デフォルトのガンマ補正が効いていないので、TextureRenderTarget欄のTargetGammaに2.2を設定しておくと見た目通りの絵が出力されます（用途によっては逆に意図した色にならない場合もあるので、ご自身の出したい絵に合わせて設定推奨です）


## 撮影用のマテリアル作成

撮影用に以下のような
　Material Domain：Surface
　Blend Mode：AlphaComposite
　Shading Model：Unlit
のマテリアルを作成します。
TextureSampleはTextureSampleParameterCubeノードで、先に作成したRenderTargetCubeがTextureSampleとして設定してあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/c7489e9b-b680-5f31-7527-4eec5fddfdc9.png)

### マテリアルの参照サイト
基本的に以下のサイトを参考にしています。

[[UE4] Unreal Engine 4.22 で360°動画(パノラマ静止画）を簡単に作ってみよう！！ |](https://www.wanimation2910.com/2019/04/15/360pano/)

Texture SampleのAlphaをOneMinusしているところはDrawMaterialtoRenderTargetノードでalphaが反転してしまうため下記サイトを参照しています。

[Draw Material To Render Target node has inverted alpha - Unreal Engine / Rendering - Unreal Engine Forums](https://forums.unrealengine.com/t/draw-material-to-render-target-node-has-inverted-alpha/366244)
> In 4.17 my workaround is:
> Set draw material to AlphaComposite blend mode;
> Use standard Alpha (not inverted) on draw material;
> Set the passthrough material to use inverted alpha output from RenderTexture (OneMinus node);
> Clear RenderTexture to (0, 0, 0, 1) before drawing.

## 撮影用のアクタの作成

撮影用のアクタを作成します。

### ScneneCaptureComponentCubeコンポーネントの追加

撮影用のアクタに以下のSceneCaptureComponentCubeを追加します。
　Texture Target：先に作成したRenderTargetCubeを設定
　Capture Source：Final Color(LDR) in RGB
　Capture Every Frame：チェック外す(負荷がかかるため)
　Caputre on Movement：チェック外す(負荷がかかるため)

![SceneCaptureComponentCube_2022-08-05 115111.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16768/95063b1a-e7f4-c15f-8cef-93f031ef49fc.png)

### 撮影用Blueprintの追加

以下のような撮影用のBlueprintを追加し、任意のタイミングで呼び出します。
* DrawMaterialtoRenderTargetノードのMaterialには先ほど作った撮影用のマテリアルを設定しています。
* RenderTargetCubeを直接ExportDiskしてもログにInvalid texture supplied.のエラーが出力され動作しません。
* ClearRenderTarget2Dをしているところはalpha反転対策です。上のマテリアルの参照サイトを参照して下さい。
* ~~ScneneCaptureComponentCubeによる撮影はCaptureSceneメソッド利用でもいいのですがアウトラインなどのポストプロセスが適用されなかったので以下のような形になっています。~~
CaptureSceneでポストプロセスを有効にするにはAlways Persist Rendering Stateをチェックすればいいみたいです。参考：[Post process for SceneCapture2D broken? - Unreal Engine / Rendering - Unreal Engine Forums](https://forums.unrealengine.com/t/post-process-for-scenecapture2d-broken/110230)

![bp2_2022-08-05 151326.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16768/8b53fb99-d244-1bba-ab6c-472f780155b8.png)