Vertex Color Baked Lighting with Wonderland Engine

ミニゴルフゲーム「“Above Paradowski”」では、Colin Freeman、 Ayushman Johri、そしてJames Kaneが、シーン内の照明を焼き付ける素晴らしい技術を使用しました。 彼らはフラグメントシェーダーでのライトマップテクスチャのルックアップを節約しながら、非常に磨きあげられた見た目を実現しました。

この記事では、この技術がなぜ賢いかを解説し、Wonderland Engineでどのように使うかを紹介します。

Vertex Color Baked Lighting with Wonderland Engine
Vertex Color Baked Lighting with Wonderland Engine

Blenderでの浮島のスクリーンショット: フラットな照明(左)、頂点カラーに焼き付けた照明(右)。

動機 

照明を計算するには時間がかかります。リアルな結果を得るためには、光の経路とバウンスを追跡する必要があり、各バウンスはさらに多くの光の経路とバウンスの計算を引き起こします。作業量が爆発的に増えます!

これはアニメーション映画がレンダリングされる方法ですが、リアルタイムVRでは、1フレームごとに数分かかる代わりに、90 HzのスタンドアロンVRデバイスで2フレーム(左右の目)を11ミリ秒で行います。 GPUレンダーファームではなく、モバイルGPUを使用します。

VRにおいて60-90 Hzを維持することは快適さと没入感に重要であるため、問題へのアプローチを別の方法で行う必要があります。 Wonderland Engineは既に多くの優れた方法と最適化を実装しており、リアルタイムシャドウがあっても高速にレンダリングしますが、非常に大規模なシーンでは、可能な限りの性能が必要です。

ライトの焼き付け 

ランタイムで照明を計算する代わりに、前もって計算して結果をアセットに保存できます。たとえば、テクスチャに影を描いたり計算したりすることで、これを行います。このプロセスを「焼き付け」と呼びます。

3Dアニメーションで使われる同じ手法を使用することもでき、非常にリアルな結果が得られます。

テクスチャは非常に細かい影や照明効果を保存するために多くの詳細を保存するのに適しています。 特にWonderland Engineのテクスチャストリーミングを使用すれば、非常に高解像度のテクスチャを使用して素晴らしい見た目のシーンを作成できます。

しかし、テクスチャは圧縮してもかなりのデータを保存することが必要です。その代わりに、ダウンロードサイズを犠牲にして、メッシュの各頂点に追加のカラー属性を保存することができます。

ライトマップテクスチャ vs 頂点カラー 

照明をテクスチャに焼き付けると、GPUでの光の計算はテクスチャ読み取りに主に削減されます。画面にレンダリングされる各ピクセルに対して、ライトマップの正しいピクセルを検索します。 すべてのレンダリングされたピクセルはライトマップから異なる色を取得でき、非常に高周波の詳細を可能にします。

一方、頂点カラーは頂点シェーダに入力され、頂点間で補間されます。詳細の頻度はメッシュの解像度に依存し、一般的に非常に低いです。 これにより、ピクセルの色の計算がさらに削減され、頂点シェーダから出力フレームバッファへの補間されたカラーを単に通過させるだけです。

パフォーマンス 

どちらがよりパフォーマンスが高いか?あらゆるパフォーマンスの質問に対する答えは常に「それ次第」であり、特にボトルネックによります。

今日の多くのWebXRアプリはドローコールに制約されています: CPUがこれ以上の作業を行うことができないため、GPUのワークロードを最適化しても効果がありません。 おそらくバッテリー寿命には影響がありますが、フレームレートには影響しません。

Wonderland Engineはこれを完全に解決し、ほとんどすべてのケースで10未満のドローコールで数万のダイナミックオブジェクトをレンダリングします。他のアプリでは多くのアニメーションキャラクターをスキニングすることにより頂点シェーディングに制約されていますが、これもVRに最適化された高性能なスキニングメソッドで効率的に処理できます。

しかし、Wonderland Engineのアプリでもフラグメントシェーディングによって制限される場合があります。フラグメントシェーダでの指令が増え、高価な操作が増えると、画面上の1ピクセルごとにGPUからより多くの計算能力が必要になります。 “Physical” (PBR) シェーダは"Phong"より多くの指令があり、それは"Flat"よりも多いです。

現代のGPUはテクスチャの読み取りが非常に速いですが、頂点フェッチ中にメッシュデータから色を読み取るだけの操作はキャッシュ効率が良く、特にこれによりメッシュから法線やテクスチャ座標を完全に省略できる場合にはその競争が難しいです。 この技術では、位置とカラーデータのみが必要な非テクスチャのFlatシェーダを使用できます。

これにより、頂点ごとに読み込むメモリの量が減少し、フラグメントごとの作業がほとんど不要になります。こうした場合、Summaryに示されているように、非常に多くの頂点数でも頂点シェーディングや頂点フェッチに制限されることはありません。

チュートリアル 

Blenderで頂点カラーに照明を焼き付け、続いてモデルをWonderland Engineにインポートすることから始めます。

Blenderで頂点カラーに焼き付け 

シーンとライトを設定します。Blenderは既に頂点カラーへの焼き付けをフルサポートしているため、プラグインは不要で、設定は簡単です。

  1. Blenderでスクリプトウィンドウを開き、次のPythonスクリプトを実行してすべての選択されたオブジェクトに頂点カラーレイヤーを追加します:
1import bpy
2
3for o in bpy.context.selected_objects:
4    if o.type != 'MESH':
5        continue
6    if len(o.data.vertex_colors) != 0:
7        continue
8
9    o.data.vertex_colors.new()
  1. Render PropertiesでレンダーエンジンをCyclesに切り替えます。
  2. さらに下にスクロールして、Bakeセクションを見つけ、Output > TargetVertex Colorsに切り替えます。
  3. Bake TypeDiffuseに設定します。
  4. このセクションの上部にあるBakeボタンを押します。

結果を表示するには、ビューポート設定を調整して結果を可視化します。

  1. 3Dビューポートでレンダータイプの隣にある矢印をクリックします(通常、上部メニューの最も右にあるボタン)。
  2. LightingFlatを選択します。
  3. ColorVertexを選択します。
Vertex Color Baked Lighting with Wonderland Engine

最後に、File > Export > glTF 2.0 (.glb/.gltf)を選択してモデルをGLBとしてエクスポートします。

Wonderland Engineへのインポート 

プロジェクト内にサブフォルダshadersを作成して以下のVertexColor.fragを作成します:

 1#include "lib/Compatibility.frag"
 2
 3#define USE_COLOR
 4
 5#define USE_MATERIAL_ID
 6#include "lib/Inputs.frag"
 7
 8void main() {
 9    outColor = fragColor;
10}

次に、モデルをWonderland Engineにインポートして、このシェーダでレンダリングします。

  1. Asset Browserに.glbファイルをドラッグ&ドロップします。
  2. そこからシーンビューにドラッグします。
  3. Views > Resources > Pipelinesへ移動して、Phong OpaqueまたはPhong Opaque Texturedを選択します。オブジェクトがテクスチャを使用しているかどうかで選択します。
  4. シェーダを新しいVertexColorシェーダに変更します。

既存のPhongパイプラインを変更することで、すべてのマテリアルを自動的に変更できます。よりクリーンなセットアップを行うには、自動的に作成された「VertexColor」パイプラインを割り当てる方法が理想的です。

これで頂点カラーがシーンに正しく適用されます。

Vertex Color Baked Lighting with Wonderland Engine

まとめ 

頂点カラーへの照明の焼き付けは、美しいビジュアルを実現する非常に効率的な方法です。 以下のビデオは、この手法で3.6百万頂点をMeta Quest 2のMeta Quest Browserで60-72 fpsでレンダリングする様子を示しています。

YouTube Video

デモでは、Wonderland Engineの独自の最適化、固定フォビエーション(1.0)、およびこのブログ投稿で説明されたメソッドを使用しています。 シーンは2ドローコールでレンダリングされます(0.9.4時点で、マルチビューレンダリングのサポートにより、これを50%削減します)。 すべてのオブジェクトはスクリプトやアニメーションによって個別に移動されても性能に悪影響を及ぼすことなく動かすことができます。

Last Update: December 2, 2022

最新情報をお届けします。