このエントリーは、Unreal Engine (UE) Advent Calendar 2021 その2 15日目の記事となります。久しぶりのUE AdventCalendarですね。
ここではUE5で搭載されているNaniteについて、ざっくりとした機能解説と関連したソースコードリーディングをしていきます。
ほんとは、数日前に公開されたThe Matrix Awakens: An Unreal Engine 5 Experienceに絡めて何か書きたかったですけどね。動くマシンが手元にないので泣く泣く諦めました。
さて気を取り直して、今回はUE5の早期リリース版を元に解説しています。そのためリリース版の実装ではここでの解説と異なる可能性があります。ま、ここで書いた内容はリリース版でもそう大きく構造は変化しないと思うので、今後も何かしら参考になると考えてます。
Naniteについてご存じ無い方のために、YouTubeの動画とNaniteのドキュメントを紹介します。
Naniteを体感してみる
Naniteについて見ていきましょう。Naniteは、3Dモデルの表示に関する機能を指します。Naniteには様々な機能が含まれています。ここでは、それら機能の一つである自動LoD(Level of Detail)をみていきます。
これまでLoDを実現する場合、表示段階別のモデルデータをあらかじめ作成しゲーム中でカメラからの距離に応じて切り替える処理を実施して処理するのが一般的でした。これはLoDのモデルデータを用意する、LoDを表示するためのプログラムを用意するといった具合に割と手間がかかる処理でした。
しかしUE5では、StaticMeshに対して「Niniteを有効」を設定することでLoDモデルが自動的に生成され、カメラの距離に応じて表示する3Dモデルも自動的に切り替えてくれます。データ作成や管理の手間がかなり削減されますね。これ。
ということで、実際に体験してみましょう。まず最初にUE4ユーザであればおなじみのシーンを用意します。
そして、椅子(SM_Chair)に対して、メニューよりNanite > Enableを選択します。これで表示されている椅子がすべてNaniteが有効となりました。デフォルトはNaniteが無効ですので。
有効化されているかどうかを確認します。Nanite Visualization > Overviewを選択します。
すると、Nanite関連デバッグに必要な表示が行われます(画面の上下に表示されている小さな画面) 。椅子は有効化しているので表示されています。しかしテーブルや床はNaniteが無効ですので表示されていません。
NaniteのLODを体感してみる
ではNiniteのLODを体感してみましょう。今回の椅子は3段階で表示が切り替わっていました。
カメラに最も近い表示。これが本来の表示となります。ポリゴン単位に色を変えて表示されています。
次にカメラから離れている時の表示です。先ほどよりは表示するポリゴン数が削減されてます。
もっともカメラから離れている時の表示です。よりポリゴン数が削減されてます。
このような処理が自動的に行われるようになりました。便利ですねぇ。
UE5のソースコードをビルドする
さて、ちょいとNaniteのソースコードを調べてみましょう。 ソースコードを調査するにはデバッグ版の方が便利なので、ソースコードからビルドしてUE5エディタを作成します。
ソースコードのビルドの流れはUE4と同じです。UE4でのソースコードビルド方法の解説記事は、[UE4] エンジンのソースコード取得とビルド手順のまとめ|株式会社ヒストリアなどいろいろあるので、そちらをみていただければ。
リポジトリには多数のブランチがありますが、その中のue5から始まっていればUE5関連のものとなってます。
UE5のソースコードビルドをさまざまなブランチをとっかえひっかえビルドして数日掛けて(うちのPCだと、めっちゃ時間かかる!)試しました。まだ開発中ということもあり、ほとんどのブランチは安定してませんでした。安定してないというのは、具体的には「エラーでビルドできない」「ビルドが成功しても利用中にフリーズする」といった感じです。
いろいろ試した結果、ue5-early-accessブランチが安定してビルド、実行できるという判断となりました(現在UE4EarlyAccessとして配付されているモノのソースコードですので、あたり前という気もしますが)。ですので、UE5のソースコードを変更してアレコレしたい場合はue5-early-accessブランチを利用するのが現時点ではいいでしょう。
気まぐれソースコードリーディング Nanite編
ではNanite関連のソースコードをざっくりとみていきましょう。Naniteという単語でソースコードを検索すると数多くのソースコードがひっかかります。いろいろ引っかかりますが、ホントにおさえておくべきソースコードが格納されているフォルダは3つかと思います。
- Engine/Source/Runtime/Renderer/Private/Nanite
- Engine/Source/Developer/MeshBuilder/Private
- Engine/Source/Runtime/Engine/Private/Rendering
では、それらのフォルダとそこにあるソースコードについて軽く解説していきます。Naniteを使いこなしてないので、説明がざっくりとなります。
Engine/Source/Runtime/Renderer/Private/Nanite フォルダ
こちらのフォルダはNaniteの表示関連に関係するソースコードが含まれてます。
ファイル名からも見当が付くでしょうが、描画のコアの部分すべてですね。UE4のソースコードはファイルサイズが大きめなものから順に読んでいくと効率的に読めることが多いです。ので、このフォルダであれば、NaniteCullRaster.cppファイルあたりでしょうか。 このファイルには、カリングとラスタライズ関連の処理が含まれています。あと、シェーダーまわりの処理もありますね。
ここにあるソースコードでは、先に紹介したデバッグ用の表示の処理をEngine/Source/Runtime/Renderer/Private/Nanite/NaniteVisualize.cppファイルにあるAddVisualizationPassesメソッドにて処理が行われています。シェーダーは、Engine/Private/Nanite/Visualize.usfです。このシェーダの中で、先ほど紹介したデバッグ関連表示の処理がすべて詰まってます。
Engine/Source/Developer/MeshBuilder/Private フォルダ
こちらのフォルダは、Naniteで表示するモデルデータの準備を行うソースコードが含まれているフォルダとなります。
Naniteで表示するLODモデルデータは、FBXファイルのインポート時にBuild Naniteにチェックを入れてインポートすることで生成されます。
そのLODモデルの生成を行うコードがEngine/Source/Developer/MeshBuilder/Private/StaticMeshBuilder.cppファイルのBuildメソッドです。
Engine/Source/Runtime/Engine/Private/Rendering フォルダ
こちらのフォルダにも、すべてのコードが対象ではありませんNanite関連のソースコードがあります。
そのうちの一つがNaniteStreamingManager.cppファイルですね。ファイル名から分かる通りNaniteStreamingManagerというのが、Naniteの3Dモデルデータをストリーミングで読み込む処理です。LoDを実現するには大量のモデルデータを扱う訳ですから、ストリーミングで読み込めないと実現する意味はないでしょうしね。
まとめ
Naniteと一口にいっても、機能が豊富なのでちゃんと理解するためには結構な時間がかかりそうです。
まだ開発中の段階でもありますので、ちゃんと調べるのは正式リリース後がよいでしょうね。