Three.jsの新しいネイティブGaussian Splatsの使い方
How to Use Three.js's New Native Gaussian Splats (ben3d.ca)
要約
Three.js r186でネイティブな3D Gaussian Splattingサポートが追加され、スプラットがエンジンの第一級市民となりました。この記事では、Gaussian Splatsの用途、数行のコードでの読み込みとレンダリング方法、ファイル形式の選択、そして現実世界のキャプチャからThree.jsシーンへのインポートまでのパイプラインについて解説します。SPZ形式が最も効率的ですが、PLY、KSPLAT、SPLAT、glTF形式にも対応しています。
全文翻訳
Three.jsの新しいネイティブGaussian Splatsの使い方
新しくリリースされたThree.js r186では、ネイティブの3D Gaussian Splattingサポートが追加され、これは非常に大きな進歩です。Splatは以前からコミュニティのアドオンを通じてThree.jsで使用可能でしたが、今やエンジンの一級市民となり、組み込みのメッシュタイプと主要フォーマット用のローダーを備えています。
基盤となる技術的な詳細は、以前の投稿「Adding Native Gaussian Splatting Support to Three.js」で解説しました。この記事は、Gaussian Splatsが何に役立つか、数行のコードでどのように読み込んでレンダリングするか、どのファイル形式を選ぶべきか、そして現実世界のキャプチャからThree.jsシーンにドロップできるスプラットまでどのように移行するかを解説する実践的なガイドです。
Gaussian Splats#
A Gaussian Splatは、従来のハードな頂点ではなく、ぼやけた、向き付けられた、色付きの3D楕円体(「スプラット」)である各点が集まったポイントクラウドです。数千から数百万個のスプラットを、奥から手前にソートしてレンダリングすると、従来の表面再構築に必要なメッシュ作成、UV展開、マテリアルベイクなしで、フォトリアリスティックな画像にブレンドされます。
これにより、スプラットは現実世界のオブジェクトやシーンを高い忠実度でキャプチャし、表示するのに最適です。特に、葉、毛皮、反射性または半透明の表面、散らかった部屋、博物館の展示品など、手作業でのモデリングが難しい被写体に適しています。スプラットは手作業で作成されたメッシュではなく写真から直接構築されるため、結果は従来の再構築作業のわずかな労力でソースマテリアルらしく見え、一度ロードすれば、シーン内の他のオブジェクトと同様に扱えます。毎フレームごとにソートされ、シェーディングされます。
[画像: Tomatoes Gaussian Splat rendered in Three.js]
ただし、知っておくべきスケーリングの制限があります。GaussianSplatは、単一のキャプチャされたオブジェクトや部屋スケールのシーン向けに構築されており、都市ブロック全体を対象とはしていません。レベル・オブ・ディテール(LOD)ストリーミングや空間セグメンテーション、カリングがないため、都市スケールのキャプチャやマルチギガバイトのスプラットクラウドは、スムーズに実行するために手動でのタイリングまたは削減が必要です。大規模シーン用のツールは、この基盤の上に後で構築でき、そのための基礎については実装投稿で詳しく説明しています。
SPZファイル の読み込み#
これが、開始から終了までのパイプライン全体です。.spzファイルを読み込み、それをメッシュでラップし、レンダリングします。
import * as THREE from 'three/webgpu';
import { SPZLoader } from 'three/addons/loaders/SPZLoader.js';
import { GaussianSplat } from 'three/addons/objects/GaussianSplat.js';
const renderer = new THREE.WebGPURenderer();
await renderer.init();
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 0.01, 100 );
camera.position.set( 0, 0.3, 2 );
// 1. スプラットデータを読み込む
const splatGeometry = await new SPZLoader().loadAsync( 'model.spz' );
// 2. メッシュでラップしてシーンに追加する
const splats = new GaussianSplat( splatGeometry );
scene.add( splats );
// 3. 通常通りレンダリングする。メッシュはデフォルトで毎フレーム自己ソートする。
renderer.setAnimationLoop( () => {
renderer.render( scene, camera );
} );
本当にこれだけです。ローダーの呼び出し1回、new GaussianSplat( geometry )のインスタンス化1回、そしてscene.add()です。GaussianSplatはTHREE.Meshを拡張しているため、他のオブジェクトと同様にシーングラフ全体と構成され、トランスフォーム、visible、レイキャスティンググループなどが期待通りに機能します。
注意すべき要件が1つあります。GaussianSplatはWebGPURendererを必要とします。レンダラーはTSLノードと深度ソート用のコンピュートシェーダーから構築されているため、インポートマップでthree/webgpuとthree/tslの両方が解決されることを確認してください。
ファイル形式の選択#
スプラットは、キャプチャまたはエクスポートされた場所に応じていくつかのファイル形式で提供され、Three.jsはそれらをカバーするために5つのローダーを提供しています。これら5つのローダーはすべて同じ内部BufferGeometry形状(position、covariance、color、およびオプションのパックされたsphericalHarmonics1..3属性)を生成するため、どのローダーを使用しても、GaussianSplatは結果を同じように消費します。
| ローダー |
| --- | --- |
| SPZLoader | .spz | 推奨。 Nianticのコンパクトなフォーマット。v4はzstd圧縮され、セクションごとにストリーミングされます。ファイルサイズが最小でロードも最速です。レガシーv1–v3(gzip)も読み取ります。 |
| GaussianSplatPLYLoader | .ply | 最も相互運用性が高い。 元の3D Gaussian Splatting研究コードおよびほとんどのトレーニング/クリーニングツールのネイティブ出力であるため、最も頻繁に受け取るフォーマットです。非圧縮で頂点ごと(テキスト/バイナリ)であり、ディスク上では大きく、.spzと比較してロードが遅いです。 |
| KSPLATLoader | .ksplat | GaussianSplats3Dビューアで使用されるフォーマット。そのパイプラインから既にアセットを持っている場合に便利です。 |
| SPLATLoader | .splat | 元の32バイト/スプラット固定フォーマット(antimatter15/splat)。非圧縮で生成が容易ですが、ディスク上では大きいです。 |
| GLTFGaussianSplatLoaderExtension | .gltf / .glb | glTF拡張機能KHR_gaussian_splattingを実装しているため、スプラットはメッシュ、カメラ、アニメーションと共に通常のglTFアセット内で転送できます。 |
フォーマットを選択できる場合は、ビューアにはSPZバージョン4を使用してください。転送サイズが最小で、パースも最速です。
PLYスプラットの読み込み#
スプラットは、元の3D Gaussian Splatting研究コードや多くのトレーニングおよびクリーニングツールのネイティブ出力であるため、.plyファイルとしてもよく提供されます。GaussianSplatPLYLoaderは、SPZLoaderやSPLATLoaderと同じパターンに従って、それらを処理します。
import { GaussianSplatPLYLoader } from 'three/addons/loaders/GaussianSplatPLYLoader.js';
import { GaussianSplat } from 'three/addons/objects/GaussianSplat.js';
const splatGeometry = await new GaussianSplatPLYLoader().loadAsync( 'point_cloud.ply' );
scene.add( new GaussianSplat( splatGeometry ) );
スプラットが生の.plyエクスポートとしてのみ存在する場合には、このローダーを使用するのが適切です。
glTFスプラットの読み込み#
スプラットがglTFファイルに埋め込まれている場合、追加の設定ステップが1つあります。GaussianSplatはWebGPURendererを必要とするため、GLTFLoaderはglTFスプラットプラグインを自動的に登録しないため、自分で登録する必要があります。
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import { GLTFGaussianSplatLoaderExtension } from 'three/addons/loaders/GLTFGaussianSplatLoaderExtension.js';
const loader = new GLTFLoader();
loader.register( ( parser ) => new GLTFGaussianSplatLoaderExtension( parser ) );
const gltf = await loader.loadAsync( 'scene.gltf' );
scene.add( gltf.scene ); // スプラットプリミティブはGaussianSplatインスタンスとして到着する
これが登録されると、KHR_gaussian_splattingを使用するメッシュプリミティブはGaussianSplat(またはマルチプリミティブメッシュの場合はそれらのGroup)としてロードされ、ファイルにそれらが含まれている場合、通常のglTFノードと同様に、メッシュ、カメラ、アニメーションと共に返されるシーングラフに着地します。
SPLATおよびKSPLATファイルの読み込み(レガシーフォーマット)#
SPLATLoaderとKSPLATLoaderは、主にレガシー互換性のために存在し、antimatter15/splatおよびGaussianSplats3Dビューアを中心に構築されたアセットとパイプラインをカバーします。
APIはSPZLoaderに非常に近いため、それらを切り替えるのは、適切なローダークラスを選択し、対応する拡張子を指すだけです。
import { SPLATLoader } from 'three/addons/loaders/SPLATLoader.js';
import { GaussianSplat } from 'three/addons/objects/GaussianSplat.js';
const splatGeometry = await new SPLATLoader().loadAsync( 'model.splat' );
scene.add( new GaussianSplat( splatGeometry ) );
import { KSPLATLoader } from 'three/addons/loaders/KSPLATLoader.js';
import { GaussianSplat } from 'three/addons/objects/GaussianSplat.js';
const splatGeometry = await new KSPLATLoader().loadAsync( 'model.ksplat' );
scene.add( new GaussianSplat( splatGeometry ) );
どちらのローダーもSPZLoaderと同じBufferGeometry形状を生成するため、GaussianSplatおよびそれ以降のすべての処理(ソート、レンダリング、glTFエクスポート)は、どのローダーを使用してそこに到達したかに関わらず、同様に動作します。
キャプチャ、クリーニング、変換、レンダリング#
現実世界の被写体からThree.jsシーン内のスプラットへの移行は、4つのステップで完了します。
1. キャプチャ#
まず、モバイルスキャンアプリを使って被写体の周りを歩きます。重複した写真またはビデオをアプリ(またはそのクラウドバックエンド)に送信すると、アプリがそれらからスプラットを再構築します。いくつかのアプリがこの機能をうまく提供しています。
- Polycam: モバイルアプリでのGaussian Splatキャプチャ、クラウド処理。
- Scaniverse: Nianticのモバイルスキャンアプリ。オンデバイスでのGaussian Splatキャプチャと
.spzへの直接エクスポートが可能。 - Luma AI: 一般消費者向けスプラットキャプチャアプリ、クラウド処理。
これら3つのいずれかを使用すれば、キャプチャから使用可能なスプラットを再構築できます。
2. クリーニング#
生の再構築結果には、浮遊するスプラット、背景のノイズ、粗いエッジが含まれる傾向があるため、出荷前にそれらをトリミングすることをお勧めします。
- Polycam には独自のトリミングおよびクリーニングツールがあり、Polycamでキャプチャした場合や、1つのアプリで作業を完結させたい場合に便利です。
- SuperSplat (PlayCanvasの無料ウェブベースエディタ)は、スプラット編集専用に設計されています。トリミング、浮遊物の削除、再エクスポートが可能です。あらゆるソースからのスプラットに対応しているため、キャプチャアプリよりも高度な制御が必要な場合や、スプラットが他の場所から来た場合に利用してください。
3. SPZへの変換#
クリーンなスプラット(通常は.plyまたは.splat形式)が得られたら、Three.jsで読み込む前に.spz v4に変換します。
- NianticのオンラインSPZコンバーター:
.ply/.splatをアップロードし、.spzをダウンロードします。 - Scaniverseでキャプチャした場合、
.spzv4を直接エクスポートするため、このステップは完全にスキップできます。
4. レンダリング#
.spzファイルが手元にあれば、プロジェクトにドロップし、この記事の冒頭の例のように、SPZLoaderとGaussianSplatで読み込みます。