Fluids & reaction

Stable Fluids / Grid-Based Fluid Simulation

安定流体法

格子上の流速と密度を更新して煙を動かす。

1 / 10

Interactive demo

Preparing the demo…

Stable Fluids / Grid-Based Fluid Simulation

Drag to orbit, Ctrl/⌘ + scroll to zoom. Use two fingers on touch screens.

This explanation is currently available in Japanese.

ひとことで

空間を格子(マス目)に区切り、各マスに流れの速度と煙の濃さを持たせて、流体の運動方程式を少しずつ解き進める方法です。Jos Stam が 1999 年に発表した「Stable Fluids」は、どんなに大きな時間刻みでも計算が発散しない(安定な)解き方を示し、ゲームやリアルタイム CG で煙や炎を動かす基本の手法になりました。

ゲームでの使いどころ

  • 煙・炎・爆発:立ちのぼる煙、たき火、爆発の火炎。GPU で 2 次元や 3 次元の格子を解き、その濃さをボリュームとして描きます(ボリュームレイマーチング)。
  • 魔法や霧のエフェクト:キャラクターの動きで霧がかき乱される、魔法陣から煙が渦を巻いて噴き出す。
  • インタラクティブな演出:タイトル画面や UI の背景で、指やマウスに反応して流れる色の液体。
  • プリベイク:Houdini や EmberGen で格子流体を計算し、フリップブックや頂点アニメーションテクスチャに焼き込んでゲームで再生する使い方も一般的です。

しくみ

流体(非圧縮のナビエ・ストークス方程式)は、次の 2 つの式で表されます。

∂u∂t=−(u⋅∇)u−1ρ∇p+ν∇2u+f,∇⋅u=0\frac{\partial \mathbf{u}}{\partial t} = -(\mathbf{u}\cdot\nabla)\mathbf{u} - \frac{1}{\rho}\nabla p + \nu\nabla^2\mathbf{u} + \mathbf{f}, \qquad \nabla\cdot\mathbf{u} = 0

1 つ目は「速度は、流れに運ばれ、圧力に押され、粘りでならされ、外力で加速する」、2 つ目は「流れは湧き出したり吸い込まれたりしない(非圧縮)」という意味です。安定流体法は、これを項ごとに分けて順番に解きます(分割法)。

  1. 外力を足す:浮力、風、プレイヤーの動きなどを速度に足します。
  2. 移流:速度そのものと煙の濃さを、流れに沿って運びます。各マスから流れを逆向きにたどり、たどり着いた場所の値を持ってくる半ラグランジュ移流を使うので、大きな時間刻みでも値が暴れません。
  3. 拡散(粘性):必要なら、周りの速度と平均をとって粘りを表します。ゲームでは、移流の補間で生じるぼやけ(数値粘性)で十分なことが多く、省略されがちです。
  4. 圧力投影:流れが湧き出したり吸い込まれたりしないよう、圧力を解いて速度を直します(圧力投影)。これが渦や、物をよけて回り込む流れを生みます。

煙の濃さや温度などの「運ばれるだけの量」は、2 の移流だけで動かします。

実装のポイント

  • GPU のテクスチャで:速度、圧力、煙を浮動小数点テクスチャに置き、ピンポンバッファで読み書きを入れ替えながら、フルスクリーンのシェーダーで各段階を計算します。2562256^2 程度なら数百マイクロ秒で済みます。
  • 格子の解像度を分ける:速度と圧力は粗い格子(例 128²)、煙は細かい格子(例 512²)にすると、少ない計算で細かい見た目が得られます。
  • 浮力:温度や煙の濃さに比例して上向きの力を足すと、煙が自然に立ちのぼります。
  • 境界:壁では、壁を通り抜ける速度を 0 にします。障害物は、そのマスを壁として扱います。

つまずきやすい点

  • ぼやけて渦が消える:半ラグランジュ移流は補間のたびに少しずつならすので、細かい渦がすぐに消えます。渦度閉じ込めで渦を補うか、MacCormack 法など高次の移流を使います。
  • 圧力の反復が足りない:ヤコビ法は収束が遅く、反復が少ないと流れが少し縮んだり膨らんだりします。見た目で許せる回数(20〜40 回)に抑えるのが普通です。
  • 3 次元はコストが大きい:1283128^3 でも 200 万マスあります。ゲームでは、局所的な小さい格子を必要な場所だけに置く、2 次元で計算して奥行きは見た目でごまかす、などの工夫をします。

デモで試すこと

  1. 3 つの煙突から立ちのぼる煙が、互いにぶつかって渦を巻き、混ざり合います。画面をドラッグすると、指でかき混ぜたように流れが起きます。
  2. 「表示」を「速度(向きを色で)」「圧力」「渦の回転」に切り替えると、煙を動かしている見えない量が見えます。圧力は、流れがぶつかる所で高く(赤)、離れていく所で低く(青)なっています。
  3. 「圧力の反復回数」を 0 にすると、圧力投影をしなくなり、煙は渦を作らず、ぼやけて広がるだけになります。
  4. 「渦度閉じ込め」を 0 にすると、細かい渦が消えて、のっぺりした煙になります。

References

GPU Gems — Fast Fluid Dynamics Simulation on the GPU ↗

A general reference for this subcategory.