[Next.js #46] Procedural Solar System ― GLSLとThree.jsで太陽系全惑星と星雲を錬成

はじめに

前回の記事では地球や土星の「環(リング)」のプロシージャル生成について解説しました。

当初、この「Procedural Solar System」プロジェクトは4つの惑星を生成する想定でスタートしました。

しかし、GLSLとノイズ関数が織りなす数学的な美しさに魅了され、妥協なき作り込みを重ねた結果、水星から海王星までの全8惑星、無数の岩石が漂う小惑星帯、そして太陽系全体を包み込む巨大な星雲に至るまで、すべてをコード(数式)のみで錬成することになりました。

今回は、この壮大な箱庭を完成させるまでの最終実装アプローチを解説します。


スクリーンショット:

動画(YouTube):

動画(PC):

巨大ガス惑星と氷惑星の錬成(木星・土星・天王星・海王星)

太陽系の外縁を回る巨大惑星たちは、それぞれが全く異なる大気とリングの特性を持っています。これまでのDomain Warping技術を応用し、各惑星のアイデンティティをGLSLで定義しました。

  • 木星 (Jupiter): 異方性スケーリングを用いてノイズを横方向(x, z軸)に強く引き伸ばし、木星特有の激しい乱流と細かい縞模様を表現。さらに局所的な座標計算を用いて、巨大な嵐「大赤斑(Great Red Spot)」を定着させました。
  • 土星 (Saturn): 穏やかなパステル調の本体に、地球のリングシェーダーをさらに高密度化させた巨大な環を実装。1Dノイズとステップ関数(step)を組み合わせることで、カッシーニの間隙のような「リングの隙間」をプロシージャルに再現しています。
  • 天王星 (Uranus): 自転軸が約98度傾いているという特異な性質を再現するため、リングのMeshを垂直(rotation.y = Math.PI / 2.0)に配置。透明感のある淡い青緑色の本体と繊細な縦リングが、独特のシルエットを生み出します。
  • 海王星 (Neptune): 太陽系で最も強い風が吹く深海の惑星。4Dノイズに強烈なワーピングをかけ、秒速2000kmの暴風と「大暗斑(Great Dark Spot)」の深淵な青を表現しました。

小惑星帯(Asteroid Belt)の実装

火星と木星の間を漂う無数の岩石は、THREE.InstancedMeshを用いて実装しました。 数千個のオブジェクトを個別のMeshとして描画するとパフォーマンスが破綻しますが、InstancedMeshを使えば1回のドローコールで大量の岩石(DodecahedronGeometry)を効率よく描画できます。それぞれの岩石には、軌道半径に基づくランダムな配置と、自転・公転の動きを与えています。

宇宙の深淵:星雲(Nebula)の追加

惑星たちが「ただの黒い背景」に浮いている状態から脱却するため、太陽系全体(半径1000)を包み込む巨大なSphereGeometryを配置しました。 THREE.BackSideで球体の内側を描画し、THREE.AdditiveBlending(加算合成)でノイズベースのガスをレンダリングすることで、宇宙空間に圧倒的な「奥行き」と「温度」を与えています。

シネマティックなカメラ操作とUI/UX

宇宙空間の鑑賞体験を向上させるため、カメラと操作系にも独自のチューニングを施しました。

  • OrbitControlsへの移行: 空間を自由に飛び回るFlyControlsから、太陽系全体を箱庭のように俯瞰・観察しやすいOrbitControlsへ変更。Damping(慣性)を有効にし、滑らかな操作感を実現しました。
  • Q/Eキーによるカメラロール(傾き): 宇宙空間における「上下」の概念をなくすため、カメラのupベクトルをQ/Eキーで回転(傾斜)できるギミックを実装しました。これにより、土星の環を斜め下から見上げるような、映画的で芸術的なアングルでの鑑賞が可能になりました。
  • インスペクターの統合: lil-guiを用いて、全惑星の色、雲のうねり、公転速度、軌道ラインの表示ON/OFFなどをリアルタイムで調整できるコントロールパネルを完備しました。

おわりに

テクスチャ画像を一切使わず、数学(ノイズ関数)とGLSLの力だけで太陽系を描き出す。一見すると冷徹なロジックの積み重ねですが、パラメータを微調整し、モニターの中で大気がうねり始めた瞬間の感動は、プロシージャル生成ならではの醍醐味です。