3D ガウシアン・スプラッティング(3DGS)実践ガイド:原理、落とし穴、そしてメッシュ変換
この1年、3D ガウシアン・スプラッティング(3D Gaussian Splatting, 3DGS)は3Dレンダリング業界を席巻した。ニコニコ動画でもX(旧Twitter)でも、思わず目を疑うようなリアルタイムレンダリングのデモを見かけるようになり、「これで従来のモデリングもNeRFも終わった」と叫ぶ人も少なくない。
しかし、実際にプロジェクトへ導入してみると、この技術には「宣伝文句と現実のギャップ」が満ち溢れていることに気づかされる。今日は3DGSの根底にあるロジックと、実戦で遭遇するあまり知られていない落とし穴を深掘りしていこう。
| 技術的観点 | 従来のフォトグラメトリ | 3D ガウシアン・スプラッティング (3DGS) |
|---|---|---|
| 世界観 | 硬い面:三角形ポリゴン + PBRテクスチャマップ | 柔らかな霧:数百万個の光る半透明な楕円体 |
| レンダリング速度 | 非常に高速(従来のGPUハードウェアラスタライズで問題なし) | 非常に高速(GPUによる深度ベースの基数ソート + オーバードロー) |
| モデル編集と物理演算 | 非常に成熟(コリジョン、スケルトン設定可能) | ほぼ編集不可(ただの点群で、衝突判定は不可能) |
| 視点依存の反射とハイライト | 複雑なシェーダーシミュレーションが必要で、通常は不自然で死んでいる | 非常にリアルで、水面やガラスの反射が視点に応じて自然に変化 |
| 3Dプリント対応 | ネイティブ対応(すでに閉じたメッシュソリッド) | 直接プリント不可(過酷なアルゴリズム抽出・変換が必要) |
本質を見抜く:3DGSとは一体何なのか?
簡単に言うと、3DGSは従来の3Dモデルにおける「点を結んで線に、線を結んで面にする」というルールを捨てている。その代わりに、**伸縮可能で、透明度を持ち、視点によって色が変化する「光る毛糸玉(ガウスカーネル)」**を大量に積み重ねて、シーンを表現している。
各ガウスカーネルは、位置、回転(クォータニオン)、スケール(共分散行列)、不透明度、色(球面調和関数 SH)を含む。 このアプローチは非常に賢い。複雑なレイトレーシングや屈折計算が不要で、これらの楕円体を距離でソートして遠くから手前へ順に描画するだけでいいため、一般的なGPUでも100FPSを超える驚異的なフレームレートを叩き出す。
スプラッティングファイルのWeb上での厳しい現実
デモ動画を見るのは楽しいが、実際に3DGSをWebページに載せてクライアントに見せるとなると、最初の壁はファイルサイズとVRAMの爆発だ。
- 標準PLY形式:完全な精度の座標と高次球面調和(Spherical Harmonics, SH)色を保持。3次SHの場合、各カーネルは視点依存の色を表現するために45個の浮動小数点数を格納する必要がある。100平方メートルの部屋のシーンなら、サイズは軽く800MBを超える。
- SPLAT形式:高度な色変化を削除(0次SH、つまり単色に格下げ)し、サイズを約250MBに圧縮。リアルな光の移ろいを犠牲にして、サイズを減らしている。
- SPZ / KSPLAT形式:積極的な量子化圧縮を施し、モバイル端末向けに特化した形式。約30MBまで圧縮可能。
私たちの実測で判明した限界:最新のモバイルブラウザ(例:iPhoneのSafari)でスムーズにレンダリングできるのは、せいぜい30万〜80万個のガウスカーネルまで。シーンが100万カーネルを超える場合、またはSPZに変換せずに数百MBのPLYファイルをそのままWebページに埋め込むと、モバイル端末では高確率で白画面クラッシュを起こす。
自分のデバイスの限界をテストしたいなら、ぜひ私たちの Any3D Splat ビューアー でローカルに読み込んで試してみてほしい。純粋にブラウザ側でWebGLまたはWebGPUを使ってレンダリングするので、サーバーの帯域幅を消費しない。
最も痛い教訓:3DGSからMeshへの変換
多くのユーザーがシーンを撮影した後、最初に思うのは「すごい!早くSTLに変換して3Dプリントしよう!」とか「Blenderにインポートしてキャラクターアニメーションを追加しよう!」ということだろう。
残酷な真実:3DGSからMeshへの変換は技術的な泥沼だ。
ガウスカーネルは本質的に光る半透明の霧の塊であり、従来のメッシュ表面抽出アルゴリズム(例:ポアソン再構成 Poisson Reconstruction)は、このような非ソリッドな対象に対して致命的な幾何学的曖昧性の問題に直面する:
- ガラスと水面の災害:3DGSでは非常にリアルな透明ガラスも、アルゴリズムはそこに浮遊するソリッドな物体があると判断する。メッシュに変換すると、まるで犬に噛まれたかのような、でこぼこで穴だらけの破片と無駄な面が生成される。
- 浮遊ノイズ(Floaters):トレーニングが完全に収束していないガウスカーネルは、空中に乱雑なモザイクを形成する。メッシュ抽出時には、空に無数の浮遊する「隕石」が出現する。
- 髪の毛や細い小枝:完全に壊滅。粗いペースト状の塊になる。
シーンに反射材質や細かい構造物が大量にある場合、メッシュ化後の品質に対する期待値は徹底的に下げるべきだ。無理に変換すると、通常は「原型を留めない泥の塊」しか得られない。
よくある質問と実戦的戦略
トレーニング用には、スマホで動画を撮るべき?それとも写真を撮るべき?
どちらでも良いが、重要なのはオーバーラップ率と軌跡だ。実測では、スマホの4K 60fpsモードで対象物の周りを安定して一周撮影し、その後10フレームごとに1枚画像を抽出する方が、手ブレしながら200枚写真を撮るよりもはるかに良い結果が得られる(モーションブラーは3DGSの天敵だ)。重要なのは:必ず周囲を回り込んで撮影すること。同じ場所に立ってその場で回転しながら録画するのはダメだ。
ゲームエンジンにインポートして物理衝突をさせるには?
ガウスカーネルで衝突判定を行うのは諦めよう。現在のUnreal Engine(UE5)やUnityでの成熟した手法は、3DGSでビジュアルをレンダリングし、対象物の周囲に非常に粗い非表示のBoxやローポリモデルを配置し、従来のMeshを物理衝突ボリューム(Collider)として使うことだ。
私のLiDAR点群データでもこの技術は使える?
一般的なLiDAR点群はXYZ座標と単一の反射色のみを含み、視点依存の光場情報がないため、球面調和パラメータをトレーニングすることはできない。 Any3D PLY ビューアー で従来の点群を直接プレビューすることはできるが、3DGSのような「光り輝く魅力」を表現するには、多視点画像ベースの完全なトレーニングパイプライン(COLMAPによる前処理)を経由する必要がある。