「Cesium みたいなもの」を作るのは、さして難しくない。 しかし「Cesium レベルの 3D エンジン」を作るとなると話が全然違う。 それほど、Cesium は神なのである。
猿真似でもいい。その神に一歩ずつ近づくために、Cesium にできて ortho-earth にできないものを、Sandcastle をなぞりながら、一つずつ消していく泥臭い作業に入った。これはその荊の道の記録である。
なんか「プロジェクト X」風ではあるが、製図係(Claude)達の粘り強さには、さすがに感動を覚えた!
方法
Sandcastle(Cesium の公式例)309 本を全部、ortho-earth の上で動かした。月・火星の例、ビューアの無い例、2D 始まりの例など 12 本は比べようがないので外し、残る 297 本を Cesium と並べて比べる。
- Cesium の顔をした ortho(facade):@ortho-earth/cesium は、Cesium の計算部品(座標、時刻、CZML、Entity、3D Tiles の読み込み)は Cesium からそのまま借り、描くところだけを ortho-earth の地球儀に差し替えたもの。「計算部品は Cesium から借りる」。だから Sandcastle のコードが 1 行も変えずにそのまま動く。
- 同じ時刻・同じカメラで撮る:本物の Cesium と ortho で同じ例を開き、同じ時刻(時計を合わせる)・同じカメラで撮り、2 枚を並べる。
- 4 つの段で採点する:画面を 64×48 のマスに切り、色と縁が何割一致するか、大きく違う塊が無いかを見る。
- 3 = 同じ絵
- 2 = 動きも数値の答えも同じだが、絵が違う
- 1 = 一部が動かない
- 0 = 動かない
- 最後は絵で決める:段は目安。判断は並べた絵(ギャラリー Sandcastle)で行う。
- 家族ごとに直す:同じ原因で崩れている例を「家族」にまとめ、家族 1 つ=PR 1 本で直す。直したら、その家族の例だけを Mac の実 GPU(WebGPU)で撮り直し、ギャラリーのカードを差し替える。
進捗の記録
最初の撮影(2026-10-25)は、3/2/1/0 = 23/120/129/24。309 本中、同じ絵はたった 23 本で、少しやばいと思った。そこからの推移:
| 日時 | 3 | 2 | 1 | 0 | 何が入ったか |
|---|---|---|---|---|---|
| 10-25 | 23 | 120 | 129 | 24 | 最初の撮影。Primitive・Model・粒子・雲などが「未対応」で止まる |
| 10-26 | 33 | 183 | 62 | 11 | facade(#672)。Cesium の部品を借りて、ほぼ全部が動くように |
| 10-26 | 100 | 129 | 54 | 10 | CZML の立体、3D Tiles、星空、地球の半透明(#698〜#703) |
| 10-27 | 117 | 126 | 44 | 8 | 模型の光(#704)、影、青い地球、衛星の軌道(#715〜#720) |
| 10-28 | 124 | 121 | 43 | 9 | 地平線、近景の地形、カメラの目標(#723〜#730) |
| 10-29 | 149 | 108 | 32 | 8 | 後処理、粒子・雲・束ね表示、海底、レンズフレア、点群、CustomShader(〜#761) |
| 10-30 | 186 | 106 | 5 | 0 | 実 GPU で 309 本を撮り直し(ortho 側は UI を隠して)。3D Tiles への画像の貼り付け、切り抜き多角形、自前の GLSL(〜#798) |
| v2.2.0 | 190 | 107 | 0 | 0 | npm の 2.2.0 と同じコードで、実 GPU で 309 本を 1 回で撮り直し。地形の負の高さ、地下の判定、雲(〜#808) |
注:10-28 までの撮影は、検定がソフトの GPU(SwiftShader、WebGPU 無し)を強制していた条件で、ortho は WebGL2 に落ちて描いていた。10-28 の途中から Mac の実 GPU(Metal、WebGPU)で撮っている。10-29 の行は、家族ごとの撮り直しをギャラリーに重ねた数。10-30 の行は、実 GPU で 309 本を撮り直した数。最後の v2.2.0 の行は、npm に出した 2.2.0 と同じコードで撮り直した最終の数。
結果
v2.2.0(npm に出したのと同じコード、Mac の実 GPU・WebGPU)で 309 本を 1 回で撮り直した結果、採点した 297 本は 3/2/1/0 = 190 / 107 / 0 / 0。動かない例も、一部が動かない例も無くなり、全部が Cesium と同じ答えを返すようになった。同じ絵は 190 本(64%)。最初の撮影の 23 本から 8 倍になった。全部の絵は Sandcastle で、Cesium と並べて見られる。
左から Before(ortho)・After(ortho、v2.2.0)・本物の Cesium。
aerometrex-san-francisco:灰色の空が青空に(色の一致 50.7% → 90.2%)

sample-height-from-3d-tiles:全面の灰色から屋上の絵に(27.7% → 98.2%)

drape-imagery-on-3d-tiles:3D Tiles の上に地図が貼られた(22.5% → 97.6%)

itwin-gaussian-splats:青一色から建物に(0.0% → 91.2%)

作ったもの
- Cesium 互換の facade(@ortho-earth/cesium)と、309 本の検定(撮影・採点・ギャラリー)
- 模型の光(太陽、HDR、環境の光を球面調和で)、影、地面の昼夜
- globe.material(標高の段彩、等高線、傾斜、方位)、海底(Cesium World Bathymetry)
- 画面の後処理(postProcessStages:シルエット、ブルーム、白黒、暗視、レンズフレア、被写界深度)
- 粒子(ParticleSystem)、雲(CloudCollection)、束ね表示(EntityCluster)
- 3D Tiles の切断面、I3S、時間で動く点群、パノラマ、Draco 圧縮の点群
- 模型の色とシルエット、地物ごとの表示切り替え、地球の半透明と地下カメラ
- 3D Tiles への画像の貼り付け(imageryLayers)
- CustomShader(GLSL を GL ではそのまま、WebGPU では WGSL に訳して)
- 近景の標高層、log depth の精度、WebGPU の WGSL の一様性の修正
諦めたもの
- 2D・Columbus 視点(geojson-simplestyle、multiple-synced-views、rotatable-2d-map):地球は 3D のみ、平面は Equal Earth という方針のまま
- VR の立体視(cardboard の例の絵は揃うが、立体には分かれない)。正射影は望遠で近似(projection)
- 地球以外の天体(月・火星)とビューアの無い例
- 絵が違うまま残った段 2(色の一致が低い順):fog-post-process、3d-tiles-feature-picking、google-streetview-panorama、video、voxel-picking、aec の 3 本、3d-tiles-terrain-classification、photogrammetry-classification、ground-primitive-dev、particle-system-weather
上流がびくともしない理由
この 7 日間で、Cesium 互換を中心に約 130 本の PR(#665〜#808)が main に入った。それでも main への自動 deploy は、本番に出す前に WebGPU・UI の全ページ検定と本番出荷物の検定を回す。途中で WGSL や深度、雲の回帰(#730〜#734、#799)もあったが、検定が見つけて配信を止め、その日のうちに直している。
ortho-earth も、v2.2.0 でフォトジェニックと言えるようになり、機能も大分充実してきた。Cesium 互換の評価手法も確立したので、今後とも更に機能に磨きをかけていく。
同じやり方で、Leaflet と Google Maps の書き方も地球儀の上で動くようになった。何が出たかは「Ortho Earth 2.2 を公開しました」に書いた。
しかし、これだけ派手に機能を弄っても上流がびくともしない。これが ortho-earth の開発手法である。