Noise & irregularity

Curl Noise

カールノイズ

渦を持つ流れ場で煙や魔力の粒子をうねらせる。

1 / 10

Interactive demo

Preparing the demo…

Curl Noise

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

This explanation is currently available in Japanese.

ひとことで

ノイズで作った「ポテンシャル場」の回転(curl)を速度として使う手法です。回転をとった場は数学的に発散がゼロになるため、粒子は渦を巻きながら流れても、特定の点に吸い込まれたり湧き出したりしません。流体を解かずに「それらしい煙の流れ」を安く得られるのが最大の魅力です。

ゲームでの使いどころ

  • 魔法・オーラ・霊体のエフェクト:キャラクターの周りをまとわりつくように漂う粒子。発散がないので、時間がたっても粒子が一点に固まらず見た目が崩れません。
  • 焚き火や煙突の煙:上昇速度にカールノイズを足すだけで、まっすぐな柱が渦を巻く煙になります。
  • ホタル・胞子・雪の舞い:ランダムな揺らぎより「空気の流れに乗っている」感じが出ます。
  • GPU パーティクルの標準部品:Unity VFX Graph や Unreal Niagara の「Curl Noise Force」は、ほぼこの手法そのものです。

しくみ

ベクトル場 v\mathbf{v} の発散 ∇⋅v\nabla\cdot\mathbf{v} は「その点から流れが湧き出す量」を表します。発散が正なら湧き出し、負なら吸い込みです。非圧縮の流体(煙や水)では発散がゼロなので、粒子の密度は流れても変わりません。

どんな滑らかなベクトル場 ψ\boldsymbol{\psi} でも、その回転の発散は恒等的にゼロになります。

v=∇×ψ,∇⋅(∇×ψ)=0\mathbf{v} = \nabla \times \boldsymbol{\psi}, \qquad \nabla \cdot (\nabla \times \boldsymbol{\psi}) = 0

そこで、3 つの独立したノイズ ψx,ψy,ψz\psi_x, \psi_y, \psi_z を並べてポテンシャル場とし、その回転を速度にします。

v=(∂ψz∂y−∂ψy∂z,  ∂ψx∂z−∂ψz∂x,  ∂ψy∂x−∂ψx∂y)\mathbf{v} = \left( \frac{\partial \psi_z}{\partial y} - \frac{\partial \psi_y}{\partial z},\; \frac{\partial \psi_x}{\partial z} - \frac{\partial \psi_z}{\partial x},\; \frac{\partial \psi_y}{\partial x} - \frac{\partial \psi_x}{\partial y} \right)

偏微分は中心差分で近似するのが簡単です。ノイズの解析的な微分が得られる実装(simplex noise の導関数版など)を使えば、評価回数を減らせます。

2D なら話はさらに単純で、スカラーのノイズ ψ(x,y)\psi(x, y) から v=(∂ψ/∂y,  −∂ψ/∂x)\mathbf{v} = (\partial\psi/\partial y,\; -\partial\psi/\partial x) を作るだけです。これは等高線に沿って流れる速度になります。

実装のポイント

GPU パーティクルの速度更新で使う GLSL の例です。snoise は任意の 3D ノイズ関数です。

  • 周波数(渦の大きさ)と強さは独立に調整できるようにしておくと、アーティストが扱いやすくなります。
  • 時間変化はノイズの入力座標をずらして作ります。ずらす速さが速すぎると流れが「ちらつく」ので、上昇速度より十分遅くします。
  • 障害物をよけさせたい場合は、ポテンシャル場を障害物の近くで 0 に近づけると、流れが表面に沿って回り込みます(Bridson らの論文の主題です)。

つまずきやすい点

  • ノイズをそのまま速度にしない:3 つのノイズ値をそのまま (vx,vy,vz)(v_x, v_y, v_z) に使うと発散を持つ場になり、粒子が吸い込み点に集まってダマになります。デモの「ノイズをそのまま使う」で確認できます。
  • 厳密な流体ではない:滑らかな連続場のカールは発散ゼロですが、差分近似や時間積分の誤差でわずかに崩れます。また、圧力や密度を解く流体シミュレーションではないので、物体に押されて煙がよける、といった双方向のやり取りは表現できません。
  • 評価コスト:差分で求めると 1 粒子あたりノイズを 18 回評価します。粒子数が多いならコンピュートシェーダーで計算するか、解析微分つきのノイズを使います。

デモで試すこと

  1. 「場面」を箱いっぱいの粒子にし、速度場を切り替えて「最も混んだ区画 / 平均」の数値を比べてください。カールノイズでは 1 倍前後に保たれ、ノイズをそのまま使うと時間とともに数値が増えていきます。
  2. 「渦の大きさ」を小さくすると、細かい乱流のような煙になります。
  3. 「速度場の矢印」を表示すると、水平断面での流れの向きが見えます。カールノイズの矢印は渦を描き、湧き出し・吸い込みの形が現れないことに注目してください。

References

Bridson et al. — Curl-Noise for Procedural Fluid Flow ↗