cm23-07

3D都市モデルに最適化されたWebGISエンジン開発に向けた基礎研究

実施事業者株式会社ユーカリヤ
実施期間2023年4月〜2024年3月
Share

3D都市モデルに最適化されたWebGISエンジンを開発するための技術調査やアーキテクチャ設計を実施。これまでにないパフォーマンスとレンダリング品質を持つ新たなWebGISの開発を目指す。

調査の目的と進め方

PLATEAUではWebGIS地図エンジンとしてCesiumを、レンダリングのためのデータフォーマットとして3D Tiles形式を採用しており、PLATEAU VIEWもこの構成となっている。Cesiumは多機能であり、PLATEAUの多様なユースケース、データの可視化をカバーしているが、Cesiumを使用してPLATEAU VIEWを開発していく中で、以下のような課題が浮上している。

1. ビジュアル

レンダリングに関する実装が地図エンジン内部に存在するため、CesiumJSの内部実装を改造せずに、より品質の高いビジュアルの作り込みを行うことが困難。

2. パフォーマンス

大規模なデータを可視化すると、アプリケーションの動作速度が低下し、ユーザー体験が悪化することがある。

3. マルチプラットフォーム

Web以外の様々なプラットフォームで、同様に動作するアプリケーションの開発・移植が困難。

以上の課題から、PLATEAU VIEWにおける地図エンジンは、以下の要件を満たす必要があると考えられる。

1. 高いビジュアルのカスタマイズ性を持ち、高品質かつ多様なレンダリング品質を実現可能とする。

2. 大規模なデータの可視化にあたって、アプリケーションの動作速度の低下を最小化し、処理速度の向上を図り、ユーザー体験をより向上させる。

3. 地図エンジンとレンダリング機構を分離し、特定のフロントエンドのプラットフォームに依存しないヘッドレスな地図エンジンとする(マルチプラットフォーム)。

そこで、本調査は、現在の様々な地図エンジンのアーキテクチャや、利用可能な最新技術を調査し、それらの技術を用いることで、以上に述べる課題を解決するような、新しい地図エンジンを実際に開発可能かどうかを、プロトタイプを開発しながら検証することを目的とする。

本調査は、以下の流れで進めていく。

1. 現状の地図エンジンに関する既存技術の調査を行う。ここでは特に、既存の地図エンジンの内部のアーキテクチャを取り上げる。

2. 地図エンジンに関連する新しい技術の調査を行う。Web技術の発展により近年使用可能になった、プログラミング言語やアーキテクチャなどの技術を調査する。

3. 調査結果をもとに、新しい地図エンジンのアーキテクチャを設計し、プロトタイプを実装することで、考案したアーキテクチャによる地図エンジンの実現可能性を確認する。

地図エンジンに関する既存技術の調査

CesiumJSやMapLibre GL JSなど、様々なWebGIS地図エンジンの内部を抽象的に見ていくと、概ね以下のような機能で構成されていることがわかった。なお、ここでの名称は便宜上つけたものであり、必ずしも一般的に定着している名称というわけではない。

地図エンジン内部の抽象的なアーキテクチャ
ライブラリ地図エンジンを外部から操作するためのAPIをアプリケーション開発者に提供する。
地図エンジンの現在の状態を取得することもできる。
レンダリングエンジン地図エンジンの状態を基に最終的な画面を描画する。
WebGLなどのグラフィックスAPIを通して、GPUにデータを転送したりコマンドを発行したりする。
メインループユーザー入力などを基に地図エンジン内部の状態(シーン・カメラ・ライト・メッシュ・レイヤーなどの位置や各種設定を含む)を変化させ、レンダリングエンジンに対し画面の描画をリクエストする。
典型的には60FPS(1秒に60回)の間隔で繰り返し実行され、約16ms以内に全ての処理を完了させる必要がある。
GISエンジンGIS特有の処理を行う。
例えば、座標変換(地心座標系・地理座標系・ENU・Webメルカトルの相互変換)や、GPUに転送する各種バッファ(頂点バッファやインデックスバッファなど)の計算を含む。

地図エンジンに関連する新しい技術の調査 

CesiumJSの開発開始から10年以上経った現在では、Web技術が大きく発展し、これまでになかった技術が使用可能になってきている。

WebAssembly (WASM):Webでは長年JavaScriptが使われてきたが、更なる高速処理を実現するために2017年に誕生した低級言語。WASMを生成することができるプログラミング言語は多岐にわたり、Rust, C/C++, Go, Java, Swift, Pythonなど多様な言語で開発することができる。現在はWASIと呼ばれる規格も策定され、WasmerやWasmtimeといったランタイムにより、Webブラウザ外でもWASMを動作させることができ、エッジやサーバーサイドのプラグインなど様々な用途への応用が期待される。

Rust:メモリ安全性や型安全性と、開発生産性や実行性能の高さを両立し、人気を博しているプログラミング言語。Stack Overflowの人気言語調査において、2023年まで8年間連続で開発者に最も愛されている言語に選ばれている。WASM開発においてもRustが最も人気のある言語であり、C/C++と同様、GCや軽量スレッドなどのランタイムを持たないことから、他のランタイムがリッチな言語(Java, Go, Pythonなど)に比べ、ランタイムなしで比較的軽量なWASMバイナリをビルド可能。

WebGPU:WebブラウザでよりモダンなGPUのAPIを提供するために新規に策定された、グラフィックスAPIの仕様。OpenGL ES 2.0をJavaScriptへ移植したのがWebGLであるが、開発が停滞する中で、ネイティブ環境ではDirect3D 12・Metal・VulkanなどのよりモダンなグラフィックスAPIが登場してきたため、それらに対応してWebGPUが策定された。GPUのより細かい制御が可能、かつ性能低下を引き起こしていたAPIの設計が改善されたことで、レンダリング速度などパフォーマンスが向上する。コンピュートシェーダによるGPGPUにも対応する。主要Webブラウザでの正式サポートは2024年3月の執筆時点ではまだ少ないが、Chromeは2023年5月リリースのChrome 113で正式にサポートした。

Entity Component System(ECS):近年のゲーム開発において採用されているアーキテクチャパターンの1つ。地図エンジンと同様にメインループの仕組みを持つゲームアプリケーションでは、毎フレームごとに大量のゲームオブジェクト(例えば主人公・敵・アイテム・ステージなど)の状態を変化させながらゲームを進行する。従来、オブジェクト指向の考え方で実装されていたこの処理を、Entity・Component・Systemという概念に基づいて実装することで、データのメモリ配置の最適化や処理の並列化によりパフォーマンスが向上する。また、モジュールの再利用性が高まり、テスタビリティや柔軟性など、開発生産性が向上する。

Shared Array Buffer:Webブラウザ上でマルチスレッド処理を行うWebWorkerは、OSにおけるマルチスレッド処理のようにメモリ空間を共有できず、メッセージパッシングの仕組みによるデータ授受を要するため処理効率が低下する。Shared Array Buffer(=SAB)を使えばWeb Workerのスレッド間でメモリ空間を共有することができ、複数スレッドでの高性能なデータ処理に寄与する可能性がある。しかし現在SABはセキュリティ上の理由により「クロスオリジン分離環境」でなければ使えない。これは非常に強い制約で、クロスオリジン分離環境で動作するアプリケーションが決して多くない中、地図エンジンがSABを前提とすると、クロスオリジン分離環境以外のWebアプリケーションをサポートしないということに繋がるため、現時点での採用は難しいと判断した。

プロトタイプの設計

以上の調査と前述した課題をもとに、本プロトタイプでは、以下のようなアーキテクチャを考案した。

ビジュアル地図エンジンのアーキテクチャ設計を見直し、レンダリングエンジンとそれ以外のCPUバウンドな処理(メインループやGISに関する演算)を分離し、レンダリングエンジンを切り替えられるようにする。

パフォーマンス:データ処理などの重い処理を担う部分は、マルチプラットフォーム性も加味して、多くの環境で同一の実装が高速に動作するWASMを使用することが良い。

マルチプラットフォーム:レンダリング以外のCPUバウンドな計算が必要であるメインループとGISエンジンは、パフォーマンスとマルチプラットフォーム性を重視し、配布形態としてWASMを、開発言語としてRustを選定する。

最も重要なことは、レンダリングエンジンと、それ以外のCPUバウンドな処理(メインループ・GISエンジン)を分離し、プラットフォームに応じてレンダリングエンジンの実装を差し替えられるようにすることである。CPUバウンドな処理にはプラットフォームを問わず高速動作するWASMを採用し、Rustで開発を行うこととした。また、メインループにおいてECSを実装するため、Rust製のゲームエンジンBevyで使用されるBevy ECSを採用した。

これにより、レンダリングエンジンとそれ以外の処理が密結合であった従来の地図エンジンよりも、より幅広いハードウェア・プラットフォーム・ユースケースへの対応力が向上すると見込まれる。CPUバウンドな処理の高速化も期待される。

プロトタイプのアーキテクチャ

本プロトタイプでは、レンダリングエンジンとしてThree.jsを採用し、以下の機能を実装可能かどうかを検証することとした。

・地球の表示
・マウス操作によるカメラの移動
・地図タイルの表示(一部の範囲・一定のズームレベルで表示)
・地形の表示(一部の範囲・一定のズームレベルで表示)
・3D Tiles・MVTの表示(建築物モデル・植生モデル・道路モデルの表示)

プロトタイプの開発結果

プロトタイプを開発することにより、上記5つの機能を実際に実装することが可能であると確認した。

特にカメラの位置やタイルのジオメトリの計算は、以下のフローを経て描画されており、WASMとレンダリングエンジンの実装を分離しながらも、両者同士を連携させながら描画することに成功した。タイルの数やポリゴンの頂点数が多すぎなければ、60FPSのフレームレートを維持しながらカメラの操作が可能であった。

1. JavaScript:マウス操作や、レイヤーの追加等を行うと、イベントが地図エンジンのキューに登録される。

2. JavaScript:タイマーにより地図エンジンのフレーム更新処理が呼び出される。

3. WASM:ECSで処理される。前回更新の後に発生したイベントを順次処理しながら、必要に応じてカメラの位置やタイルのジオメトリなどの計算を行い、EntityやComponentを作成・更新・削除する。ECSでの処理の最後に、ECSの世界内で発生したEntityやComponentの変更(=地図エンジンの状態変化)を収集して、JavaScriptから取得できるようにする。

4. JavaScript:WASM内部で発生した地図エンジンの状態変化を取得し、Three.jsの各種オブジェクトに反映させる。

5. JavaScript:Three.jsのレンダリングを呼び出し、画面を描画する。

6. 画面に結果が表示され、フレーム更新完了。

地図タイルには国土地理院の地図タイルを、地形の表示には国土地理院の標高タイルを使用した。タイルはWebメルカトルの座標系が用いられており、タイルのジオメトリを計算する際に、Webメルカトルの座標をワールド座標系である地心座標系に変換する必要がある。この処理はWASM内で行われる。

タイルを敷き詰めることにより地球を描画した様子
タイルをワイヤーフレームで表示
3D Tilesの建築物モデル、MVTの道路モデルを描画した様子
3D Tilesの建築物モデル・植生モデル、MVTの道路モデルを描画した様子
国土地理院の標高タイルを読み込み富士山とその周辺の地形を描画した様子
富士山をワイヤーフレームで表示

また、今回のプロトタイプでは、レンダリングエンジンにThree.jsを使用していることから、シェーダを独自にカスタマイズして、見た目を大きく変更することが可能である。これは、今回開発する地図エンジンが持つ「レンダリングエンジンの分離」によって得られた利点である。

レンダリングエンジンの分離によって生まれるこの利点を確認するため、ここでは例として「SFのようなサイバー空間」をイメージした画面作りを試みた。その結果を以下に示す。これらの結果から、レンダリングエンジンの分離によって、従来の地図エンジンでは難しかった画面作りが可能になっていることが示唆される。

なお、この画面作りにおいては、Three.jsを使用して以下の実装を行なった。

・エッジを光らせるため、別途、各メッシュのジオメトリデータをもとに、エッジを表すジオメトリをEdgesGeometryを使用して計算し、シーンに追加している。

・メッシュに適用するマテリアルは、LineBasicMaterialを拡張して実装を行なった。実際の画面では、白い光の波が3Dモデル上を地面側から上空側へと流れていくアニメーションを見ることができる。このアニメーションを正しく実装するためには、シェーダが各頂点の楕円体高(=地球楕円体表面からの高さ)を取得できる必要があるが、地心座標系のためそのままでは取得することができない。各頂点の楕円体高を事前計算して頂点属性に格納する方法もあるが、その分GPUへの転送量が増えVRAMを消費してしまう。そこで頂点シェーダ内で各頂点の楕円体高を地心座標系から変換して求め、その結果を基にフラグメントシェーダで白く光らせるかどうかを計算している。

・各メッシュのエッジのみにブルームのポストプロセッシングを適用し、エッジが光っているように見せている。

サイバー空間のような表現で街並みを描画した様子
サイバー空間のような表現で描画された街並みを一望した様子
サイバー空間のような表現で富士山周辺を描画した様子

最後に、今後も地図エンジンの開発を継続し、プロダクションレベルまで到達するために、将来的に解決が必要と思われる課題を整理する。

1. Webにおけるマルチスレッディングの制約:前述の通り、現在のところクロスオリジン分離の制約によりSharedArrayBuffer(SAB)を使用することが困難である。この制約により、Webではマルチスレッドを用いた並行処理の実装が大きく制限される。また、WASM Threadsなどの関連仕様は2023年1月現在、未だ策定途中である。なお、策定や実装が進んだとしてもSABの制約は依然として残る。

2. レンダリングエンジンとWASM間のデータの送受信の最適化が必要:WASMは処理を高速化する可能性があるが、WASM外部(例えばJavaScript)とのデータのやり取りの頻度が多くなってしまうと、かえってWASMを採用しない実装よりもパフォーマンスが低下してしまう可能性がある。よりパフォーマンスを高めるため、なるべくWASMとレンダリングエンジン間のデータのやり取りの回数や、データのコピーを最小限にすることが望ましい。

3. Dracoのデコード等がWASM上で処理できない: WASMには外部のWASMをライブラリとして利用する仕組みがまだ確立されておらず、またC/C++のライブラリをFFIを通して呼び出すといった方法も困難である。よってDraco(glTF圧縮ライブラリ)のようなC/C++で実装されたライブラリを使用するには、Webの世界を通して間接的に呼び出すか、Rustによるピュア実装(=他言語で開発されたライブラリに依存しない、全てRustで書かれた実装)が必要となり、既存の資産を活用することが難しい場合がある。

以上の課題を解決しつつ、対応データフォーマットの増加、マルチスレッドを活用したデータ読込の効率化、シェーダの最適化や新規実装を含むビジュアルの強化などの工夫により、より軽量でリッチなビジュアルを持つマルチプラットフォームな地図エンジンの開発が可能と見込まれる。

今後の展望

本調査は、現在のさまざまな地図エンジンのアーキテクチャや、新しい地図エンジンで利用可能な最新技術を調査し、WASM・Rust・ECSなどの技術を用いることで、従来の地図エンジンが持つ課題を解決するような、新しい地図エンジンの開発が可能かどうかを、プロトタイプを開発しながら検証した。

プロトタイプの開発においては、ECSのライブラリとしてBevy ECSを採用し、レンダリングエンジンにはThree.jsを採用し、メインループ等はWASMで動作しレンダリングはThree.jsを通してWebGLで行う、プロトタイプの開発を行った。これにより、地図エンジンのCPUバウンドな処理とレンダリングエンジンを分離した状態で動作する地図エンジンが開発可能であることが確かめられた。

一方で、十分にハードウェアの性能を引き出す地図エンジンを開発するには、Webにおけるマルチスレッディングの制約をはじめとする課題が依然として存在している。そのうち以下の課題については、以下のような展望で解決を目指す。

1. レンダリングエンジンとWASM間のデータの送受信の最適化が必要

現状、地図エンジンのWASMとレンダリングエンジン間の通信(データ授受)は、フレーム更新後に結果をレンダリングエンジンに反映させるタイミングだけでなく、マウス操作などのユーザー入力が発生するたびに行われている。しかし実際にはこれらのデータを使用するのは、フレーム更新が実行された時のみである。そこでフレーム更新が発生するまではJavaScript側で発生したイベントのデータを溜め込んでおき、フレーム更新時に一括でWASMへ転送するといったアプローチを試みることができる。これによりWASMとレンダリングエンジン間のデータ授受の頻度を減らすことができ、パフォーマンスの向上につながる可能性がある。

2. Webにおけるマルチスレッディングの制約

WebWorkerを積極的に使用することを検討する。具体的には、レンダリングエンジンをWebWorker化する(OffscreenCanvasを用いてレンダリングをワーカーで行う)、WASMの処理全体をWebWorker化する、WASMの計算量が多い一部処理のみ(ジオメトリの計算など)をWebWorker化する、といったパターンが考えられる。更に、WebWorkerを複数同時に起動させ、優先度つきワーカープールのような仕組みを構築することで、例えばカメラに近いタイルの処理を優先するといった処理を可能にしつつ、小さいタスクを効率よく実行する仕組みが実現する可能性がある。これにより、地図エンジンのUIの応答停止を最小化することができ、ユーザー体験が向上する可能性がある。

3. Dracoのデコード等がWASM上で処理できない

直近では、3D Tilesのデータ読み込み時にJavaScript側でDracoのデコードまでを行い、その結果をWASM側に転送することを検討する。長期的には、Rustのみで実装されたDracoのライブラリを開発することも考えられる。