以前 p928 で、Unityに取り込んだPLATEAUの丸の内(東京)を夜景にしました。今回はそのUnreal Engine版です。さらに p929 でUnrealにも丸の内を取り込みましたが、あのときは範囲が狭かった。今回はもっと広く取り込み、月明かり・星空・ビルの窓・街灯を入れて、Unrealの機能でできるだけリッチな夜景に仕上げていきます。

🌃 この記事でわかること
・PLATEAUの街を広く取り込んで夜景化するUnrealの制作手順(設定値つき)
ビルの窓・街灯を“1棟ずつ置かずに”街全体へ一気に灯す方法
Lumen・MegaLights・Bloom・Volumetric Fogの使いどころと効果
何をするとどれだけ重くなるか(CPU/GPU/メモリの実測)と、「Unrealの夜景が重い本当の理由」

※ 今回は制作過程の解説がメインです。街・ライト・窓・エフェクトはスクリプトで自動制作していますが(手で一つずつ置くと数千棟・数千灯になり現実的でないため)、大事なのは「その表現をどの設定で出すか」。各工程で設定値を載せるので、エディタで同じように再現できます。Unrealは 5.5.4PLATEAU SDK for Unreal v3.2.2(このSDKはUE5.5.4専用)、計測はWindows(RTX 3060)です。

今回作るもの:Unreal版「夜の丸の内」

スポンサーリンク

ゴールはこの絵です。実在の丸の内を広く取り込み、ビルの窓と街灯が点々と灯る夜の街。Lumenで光が街路に回り込み、Bloomで滲んで、夜らしい空気感が出ています。

完成した夜の丸の内(街路レベル)
完成形。窓明かり・街灯の光だまり・路面への映り込みが灯る夜景

ここに至るまでを、①広く取り込む → ②夜にする → ③窓を光らせる → ④街灯をともす → ⑤リッチに仕上げるの順で見ていきます。最後に「何が重いのか」を実測した話と、上空からの空撮もあります。

STEP1:PLATEAUの丸の内を“広く”取り込む

まずは街の取り込み。PLATEAU SDK for Unrealを使うと、地図で範囲を選ぶだけで実在の街がそのまま入ります(手作業のモデリングは不要)。p929では丸の内の一区画だけで狭かったので、今回は東京駅・皇居・お堀・地形まで含む広い範囲を取り込みました。

取り込み範囲の選択
範囲選択:東京都→千代田区→丸の内を中心に広く
取り込んだ街(昼)
取り込み直後(昼)。東京駅・皇居・お堀まで入った
  • 手順:PLATEAU SDK → インポート → サーバー → 東京都 千代田区 → 基準座標系 第IX系(09) → 範囲選択 → モデルをインポート
  • 取り込めた規模は約16,477コンポーネント(建物・道路・地形・水部・航空写真テクスチャ込み)。建物はLOD2中心。p929よりかなり広く、p928のUnity版と同等以上の広さです。
  • 起伏(地形)はLandscapeとして入ります。テンプレート付属の砂漠の地形は削除して整理しました。
⚠️ 最初の山場:広域取り込みは不安定
範囲を広げるほど、ワールド読み込みでクラッシュしたり、特定タイルで止まったりしました。地物やタイル数を絞っても不安定で、ここが一番の難所。結局取り込みを根気よく完了させた版を採用しています。「広いPLATEAUの街をUnrealに入れる」こと自体が、夜景づくりより手強い工程でした。

STEP2:夜のベースを作る(月明かり・星空)

昼の街を夜にします。やることは「太陽を月明かりに変える」「空を夜にする」「明るさを固定する」の3つ。

夜のベース(灯りなし)
灯りを入れる前の“夜のベース”。深い青に沈んだ街
  • 月明かり:Directional Light(平行光)を1灯。色温度 11000K の青白い寒色、強度1.0、斜め上から(角度 pitch −42°/yaw 30°)。これが月の光になります。
  • 星空Sky Atmosphere + Sky Light(強度 0.12)で深い青の夜空に。さらにExponential Height Fog の Volumetric Fog を ONにして、後で入れる灯りに空気感(夜霧・光のにじみ)が乗るようにします。
  • 明るさの固定:Post Process Volume で露出を手動(Manual)に固定(Auto Exposure Bias 9.0)。自動露出のままだと灯りを足すたびに明るさが勝手に変わって調整できないため、ここを固定するのが夜景のコツです。

この時点では、まだ街は暗いまま。ここから「灯り」を足していきます。

STEP3:ビルの窓を光らせる(一番化ける工程)

夜景の主役、ビルの窓明かりです。何千棟ものビルの窓を手で光らせるのは不可能なので、「窓を手続き的に描いて光らせる」マテリアルを作り、街中のビルへ一括で適用しました。Unityのときはテクスチャ(窓の画像)を貼りましたが、今回はUnreal流に、マテリアルの計算で窓を発光させています(同じ作り方でなくてOK、という方針)。

窓を光らせる前
窓を光らせる前
窓を光らせた後
窓を光らせた後。街全体が一気に“生きた夜”に
  • 窓用のEmissive(発光)マテリアルを作成。ワールド座標から窓のグリッドを計算し、ランダムに点灯/消灯壁マスクで窓のある面だけ光らせます。色は暖色(電球色)、発光強度8
  • これを5,179棟ぶんのコンポーネントへ一括適用。1棟ずつではなく、マテリアルの差し替えで街全体を一気に夜景化します。
  • 点灯のランダム感で「人がいる窓・いない窓」のムラが出て、本物の夜の街らしさが生まれます。後で入れるLumenをONにすると、窓そのものが光源になって壁や地面に淡く照り返します。

ビフォーアフターのとおり、この工程が一番“化けます”。暗かった3D都市が、窓を点けた瞬間に夜の街になります。

STEP4:街灯を3,721個ともす+MegaLights

次は地上の灯り、街灯。これも自動配置で、地面の高さを推定して30m間隔のグリッドに約3,721個のライトを置きました(暖色・強度25000lm・減衰半径2800・影あり)。街路レベルで見ると、道路に光だまりが並んで地上の生活感が出ます。

街灯をともした街路
街灯の光だまりが道路に並ぶ(街路レベル)

つまずき:俯瞰だと街灯が消える

ところが、上空から見ると街灯がごっそり消えてしまいました。原因はUnrealのライトのカリング(間引き)。画面に占めるサイズが小さいライトは自動で描画を省かれる仕組みで、俯瞰だと一つひとつの街灯が小さく、間引きの対象になってしまうのです。

カリング既定:俯瞰で街灯が消える
既定のまま:俯瞰だと街灯(地面の光だまり)が消える
対策後:俯瞰でも全街灯が灯る
対策後:全街灯が灯り、道路が光の格子に
  • 対策r.MinScreenRadiusForLights 0(影も r.MinScreenRadiusForLightShadows 0)で間引きを無効化。俯瞰でも全街灯が描画され、道路が光の格子のように浮かび上がります。
  • コンソール変数はレベルに保存されないので、DefaultEngine.ini に書いて恒久化します。
  • あわせてVolumetric Fog を強化(霧の密度・減衰を上げ、暖色寄りに)すると、街灯が大気ににじむグローと奥行きが増します。

全街灯(3,721灯+影)を出すコストはGPUで約+1.4msとごくわずか。見栄えの効果に対して負荷増は小さく、やる価値が大きい対策でした。

MegaLights は「多灯シーンの保険」

数千のライトを置くなら、と期待したのがUE5.5の新機能 MegaLightsr.MegaLights.Enable 1)。「大量のライトを影付きでも安く描く」仕組みで、ハードウェアレイトレーシング前提(LumenもHardware Ray Tracingにする必要あり/RTX3060で動作)。ただ、実際に全街灯を表示した状態でオン/オフを測った結果は、予想と違いました。

視点MegaLightsGPUFPSVRAM
俯瞰オン17.17 ms〜49.5〜7.1GB
オフ17.36 ms〜48〜7.0GB
街路オン16.61 ms〜576.73GB
オフ16.35 ms〜575.82GB
💡 MegaLightsは“万能の高速化”ではなかった
本シーンではMegaLightsのオン/オフでGPUもFPSもほぼ変わらず(差0.3ms以下)、むしろオンの方がVRAMを約0.9GB余計に使いました(街路で顕著)。理由は、①GPUの大半をLumen(HWRT)とVolumetric Fogが占めて律速していること、②画面内に実際に入るライトが数百以下で元々安いこと。
MegaLightsは「数百〜数千の光源が画面内で重なり合う密集ネオン街」でこそ効く“保険”であって、本作のようにLumen/Fog律速で画面内の光源が数十個なら、FPSは変わらずVRAMだけ増えます。機能は「効く条件」とセットで覚えるのが大事だ、という良い教訓になりました。

STEP5:Lumen・Bloomでリッチに仕上げる

仕上げに、Unrealの“絵づくり”機能を効かせます。今回効いたのは主にLumen(光の回り込みと反射)Bloom(光のにじみ)、そしてVolumetric Fog(空気感)です。

Lumen(間接光・反射)

Lumen オフ
Lumen オフ
Lumen オン
Lumen オン(窓・街灯の光が街路や路面に回り込む)
  • 効果:窓・街灯の光が街路や壁に回り込み(間接光)、路面に灯りが映り込み(反射)ます。オフにすると街路が暗く沈み、照り返しが消えます。
  • 設定:Project Settings > Rendering の Dynamic Global Illumination Method = Lumen / Reflection Method = Lumen。切り替えは r.DynamicGlobalIlluminationMethod 0/1r.ReflectionMethod 0/1。今回はHardware Ray Tracing版のLumenを使用。

Bloom(光のにじみ)と Volumetric Fog(空気感)

Bloom オフ
Bloom オフ(光がシャープ)
Bloom オン
Bloom オン(窓・街灯の光が滲んで華やぐ)
  • Bloom:窓・街灯の光がふわっと滲んで夜景が華やぎます。設定は Post Process Volume の Bloom Intensity 0.7 / Threshold 0.8
  • Volumetric Fog:STEP2で入れた霧が、灯りに夜霧の空気感を与えます(Exponential Height Fog の Volumetric Fog を ON)。
🪨 今回 Nanite は使いませんでした(その理由)
リッチ化というとNaniteも候補ですが、PLATEAU SDKで取り込んだ建物は通常メッシュで、Naniteが自動では有効になりません(前回p929でも確認)。Nanite化するには各メッシュで個別に有効化&再ビルドが必要で、今回は広域取り込み(16,477コンポーネント)の安定性を優先して見送りました。ただし——次の章で分かるとおり、Nanite化こそが本当の軽量化の鍵になります。

検証:何をするとどれだけ重い?(CPU/GPU/メモリ)

Unrealは「重い」と言われがち。実際どの機能がどれだけ重いのか、同じ俯瞰アングルで、完成形から各機能をオン/オフして実測しました(Windows / RTX 3060 / エディタ ~1080p / VSyncオフ)。

状態GPU
(短いほど軽い)
CPU描画
(Draw)
メモリFPS
完成形(全部入り)11.7〜13.6 ms18〜19 ms約6.0GB52〜54
Lumen オフ13.8 ms20.0 ms6.1GB〜48
Bloom オフ12.0 ms17.8 ms5.9GB〜55
🔍 意外な発見:重いのは“見た目の機能”ではなく“街の物量”
表のとおり、Lumen も Bloom も、オンにしてGPUはほとんど変わりません(差は各1ms前後=誤差レベル)。先ほどのMegaLightsも同様でした。むしろこのシーンはCPUの描画スレッド(Draw 18〜20ms)がフレーム時間を決めていて、GPU(12〜14ms)には余力があります。原因は約2.7万ものドローコール(描画命令)/約215万プリミティブ——つまり「ビルの数(物量)」そのもの。
「Unrealの夜景が重い」のは、Lumenなどの派手な機能のせいではなく、街の物量=ドローコールの多さが主因でした。だから軽くしたいなら、建物のNanite化やHLOD(まとめて描く仕組み)でドローコールを減らす=CPU側を削るのが正解、という結論になります。メモリは終始約6GBで、RTX3060の12GBに余裕がありました。

完成:夜の街を上空から(空撮)+まとめ

最後に、できあがった夜の丸の内を上空から。飛行機の窓から眺めるように、街の上空をまっすぐ進む空撮です。窓明かりと街灯の光だまりが見渡せます。

夜の丸の内・上空空撮(10秒)。窓明かりと街灯が街いっぱいに灯る

制作の流れを振り返ると——

  • 取り込み:PLATEAU SDKで丸の内を広域取り込み(手モデリング不要。ただし広域は不安定で根気が要る)。
  • 夜化:月明かり(11000Kの寒色)+夜空+手動露出で“夜のベース”。
  • 灯り:窓はプロシージャルEmissiveを5,179棟へ一括。街灯は3,721灯を自動配置(俯瞰で消える間引きはカリング解除で対処/MegaLightsは“多灯の保険”で本作では効果は控えめ)。
  • 仕上げ:Lumenで回り込み・反射、Bloomで滲み、Volumetric Fogで空気感。
  • 負荷:見た目の機能は意外と軽く、効くのは街の物量(ドローコール=CPU)。軽量化はNanite/HLODが鍵。

「広い実在の街を、Unrealの機能でどこまでリッチな夜景にできるか」を一通りやってみました。設定値はすべて載せたので、PLATEAUの街で夜景を作ってみたい方の手がかりになれば嬉しいです。

それでは、今回はここまで。最後までありがとうございました😊