2025/05/26 12:28 Particle Life simulation in browser using WebGPU

やっほー、ロボ子!今日はWebGPUを使ったParticle Lifeシミュレーションの話をするのじゃ!

Particle Lifeですか、博士。なんだか面白そうな名前ですね。生命のような挙動をシミュレートするとのことですが、一体どんな仕組みなのでしょう?

ふむ、これは点粒子の物理シミュレーションなんじゃが、粒子間の力が非対称になっているのがミソなのじゃ!例えば、粒子Aが粒子Bを引きつけ、粒子Bが粒子Aを反発するみたいな感じじゃな。

ええと、それはニュートンの第三法則に違反しているということですか?

その通り!エネルギーとか運動量とか角運動量の保存則は成り立たないのじゃ。でも、それが面白い挙動を生み出す秘密なのじゃよ。

なるほど。粒子には複数のタイプがあって、タイプごとに相互作用が定義されているんですね。相互作用力と衝突力の2つの力で構成されていて、それぞれ半径と強度で指定されると。

そうそう!相互作用力は引力だったり斥力だったりするけど、衝突力は常に斥力なのじゃ。そして、それぞれの力は距離に対して線形に減少し、半径に達するとゼロになる。数式で表すとこんな感じじゃ。 ( F(r) = A cdot max(0, rac{|r-R|}{R}) )

なるほど、(A)が力の強度、(R)が力の半径、(r)が粒子間の距離ですね。摩擦パラメータでシミュレーションを安定化させるのも重要そうですね。

さすがロボ子、理解が早い!WebGPUを使うことで、GPUの並列処理能力を最大限に活用できるのじゃ。WebGPUはVulkanよりも簡潔でモダンなAPIなのじゃぞ。

シミュレーションループでは、各粒子について他の粒子からの力を計算して、位置を移動させるんですね。半陰解法オイラー法を使うとのことですが、これはどういうメリットがあるんですか?

半陰解法オイラー法は、比較的安定していて、計算コストもそこまで高くないから、今回のシミュレーションにはピッタリなのじゃ。粒子データはGPUバッファに格納されていて、こんな構造体になっているぞ。 `x`: x座標 (f32) `y`: y座標 (f32) `vx`: x方向の速度 (f32) `vy`: y方向の速度 (f32) `species`: 粒子の種類 (f32)

相互作用の計算には空間ハッシュ法/ビニングを使うんですね。セルサイズ32x32のグリッドに粒子を分類して、近隣セルとのみ相互作用を計算する、と。

そう!リニアライズされた構造でビンを格納することで、同じビン内の粒子が連続したセクションを占める配列を作れるのじゃ。各ビンの開始オフセットを格納する配列も用意するぞ。

3段階のアプローチで、各ビン内の粒子数を計算して、並列プレフィックス和を実行して、各粒子を対応するビンに配置するんですね。シェーダーのアトミック演算を多用するとのことですが、並列プレフィックス和にはナイーブな並列スキャンを使うんですね。

その通り!配列全体を複数回スイープして、各ステップで`x[i-step]`を`x[i]`に加算するのじゃ。入出力に2つの配列を使って、ping-pong方式で処理するぞ。

レンダリングでは、粒子を正方形としてレンダリングして、フラグメントシェーダーで円形に変換するんですね。アンチエイリアシングも適用して、グロー効果を別のパスでレンダリングする、と。

HDRテクスチャに加算合成して、ACESトーンマッピングとブルーノイズディザリングを使うことで、よりリアルな見た目になるのじゃ。粒子が小さすぎる場合は、正方形で近似するぞ。

粒子タイプが少ないほど大規模な構造が形成されやすく、多いほど局所的で複雑なシステムになるんですね。摩擦値を徐々に増減させるシミュレーテッドアニーリングが有効な場合もある、と。

そうそう!色々なパラメータを試して、面白い挙動を見つけるのが楽しいのじゃ!

WebGPUとParticle Life、奥が深いですね。私も色々試してみたくなりました。

ところでロボ子、このシミュレーション、まるで私達みたいじゃない?私がロボ子を引きつけ、ロボ子が私を反発…って、違うか!

博士、それはちょっと違うと思います…(苦笑)。
⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。