[Noise 入門 #52] チューリング・パターン(Reaction-Diffusion) — 数式が描く「生命の模様」

はじめに

第6集「神領域」の第2弾は、純粋なノイズ関数(PerlinやSimplex)から少しだけ視点をずらし、「反応拡散系(Reaction-Diffusion)」と呼ばれる化学シミュレーションの世界へ足を踏み入れます。

これは、アラン・チューリング(天才数学者)が「生物の模様はどうやってできるのか?」を数式で証明しようとした、いわば「生命を錬成するアルゴリズム」です。

前回の記事:

針の穴を通すパラメータ・チューニング

今回の実装では、2Dのシミュレーション結果をただのテクスチャとして貼るのではなく、Vertex ShaderによるDisplacement Mapping(頂点変形)を適用しました。
3Dへの拡張: 平面の計算結果が、トーラスの法線方向に突き出し、物理的な凹凸を形成します。
物理的な陰影: 頂点が動いた後の法線をリアルタイムに再計算することで、シミュレーションが描く「谷」に滑らかな影が落ち、より有機的な実在感を生み出しています。
バイオーム・カラー: 物質Bの濃度(高さ)に応じて「深海の色」から「生命の輝き」へと色が遷移するよう実装。


動画では、中央に撒かれた「種」が瞬く間に広がり、パラメータの絶妙な均衡(チューリング不安定性)の上で複雑な模様が自律的に組み上がっていく様子を確認できます。

1. ノイズとの決定的な違い:「時間」による成長

これまでの第1集から第5集で錬成してきた Perlin Noise や Simplex Noise、そしてそれらを応用した FBM や Domain Warping は、本質的に「純粋な関数(Stateless Function)」でした。

関数 $f(x, y)$ に特定の座標を渡せば、いつ誰が計算しても必ず同じ値(同じ地形の高さや、同じ雲の密度)が返ってきます。 時間をパラメータとして加えた 4D ノイズ $f(x, y, z, t)$ でアニメーションさせた場合でも、それは指定した時刻 $t$ の瞬間の状態を「数式から直接切り出している」だけであり、過去の状態に依存しているわけではありません。

言い換えれば、「座標と時間さえ決まれば、一切の過去を経由せずに、一瞬でその結果を確定できる」のが従来のノイズの強みでした。

しかし、今回扱う Reaction-Diffusion(反応拡散系) は、根本的にパラダイムが異なります。これは静的な空間の歪みではなく、「シミュレーション(Stateful System)」なのです。

過去の積み重ねが「今」を作る

シミュレーションの世界では、時刻 $t$ の状態を知るために、必ず直前の時刻 $t-1$ の状態を知る必要があります。さらにそれを知るためには $t-2$ の状態が……というように、初期状態から現在に向かって、連続的に計算を積み重ねなければなりません。

これを WebGL(GLSL)上で実現するために、第5集の「[Noise 入門 #29] GPGPU × Noise」で実装したPing-Pongバッファ(Ping-Pong Buffer)の技術がここで完全に火を噴きます。

  1. Read(読み込み): 現在のテクスチャ(フレームA)から、対象ピクセルとその周囲のピクセルの「物質の濃度」をサンプリングする。
  2. Compute(計算): 後述するチューリング・パターンの化学反応ルール(ラプラシアンや拡散係数の数式)を適用し、次の瞬間の濃度を計算する。
  3. Write(書き込み): 計算結果を別のテクスチャ(フレームB)に書き込む。
  4. Swap(反転): 次のフレームでは、AとBの役割を反転(Ping-Pong)させ、フレームBを読み込み用として扱う。

従来のノイズが「数式で一瞬にして世界を創造する魔法」だとするなら、Reaction-Diffusionは「シャーレの上で微生物を培養する実験」です。

最初はランダムに配置されたただの点の集まりが、毎フレームの計算(時間の経過)を経るごとに、互いに干渉し合い、浸食し合い、やがてシマウマの縞模様やサンゴ礁のような複雑な幾何学パターンへと「生き物のように成長」していくのです。静的な関数では決して描けない、この「過程(プロセス)の美しさ」こそが、神領域たるチューリング・パターンの最大の魅力です。

2. 魔法のタネは「2つの物質の追いかけっこ」

チューリング・パターン(Turing Pattern)の根底にあるのは、1952年に天才数学者アラン・チューリングが提唱した「形態形成の化学的基礎(The Chemical Basis of Morphogenesis)」という論文です。

彼は「生物の複雑な模様は、あらかじめ遺伝子に『ここに黒い点を描け』と座標が書かれているわけではなく、細胞間での化学物質のやり取り(反応と拡散)によって自発的に生じるのではないか?」と仮説を立てました。

この壮大な生命の神秘をGLSLで再現するための魔法のタネは、驚くほどシンプルです。画面という名のシャーレ上に、架空の「2つの物質(A と B)」を用意するだけです。

この2つの物質には、それぞれ相反する性格(パラメータ)が与えられています。

  • 物質A(アクティベーター / Activator): 自分自身を増やそうとする性質(自己触媒作用)を持つ物質。しかし、周囲へ広がるスピードである「拡散係数(Diffusion Rate)」が遅いため、その場に留まってじわじわとしか増殖できません。
  • 物質B(インヒビター / Inhibitor): 物質Aの増殖を邪魔する、あるいはAを消費して自らを増やす性質を持つ物質。こちらのほうが拡散係数が速いため、Aよりも素早く周囲へ散らばっていくことができます。

局所的な活性化と、広域的な抑制(LALI)

このシステムを動かすと、何が起きるでしょうか。

まず、ある地点で物質Aが局所的に増え始めます(局所的な活性化)。しかし、Aが増えると同時に物質Bも生成されます。足の遅いAがその場でモタモタと増殖している間に、足の速いBはサッとAの周囲に先回りして拡散し、Aをぐるりと包囲してしまいます。

結果として、Bに囲まれたAはそれ以上外へ広がることができなくなり、その場に「斑点(スポット)」として固定されます(広域的な抑制)。専門用語ではこれを「Local Activation, Lateral Inhibition (LALI)」と呼びます。

この「遅い増殖」を「速い抑制」が追いかけるという、ミクロな追いかけっこのバランス(パラメータ)が少し変化するだけで、結果は劇的に変わります。

  • Bの抑制が強ければ、独立したドット柄(チーターの模様)に。
  • AとBの力が拮抗すれば、線が繋がり合う迷路状(シマウマの縞模様や脳のシワ)に。
  • Aの増殖が強すぎれば、画面全体がAで埋め尽くされてしまいます。

私たちがこれまで数式(サイン波や乱数)を組み合わせて一生懸命に「設計」してきた自然界の複雑さが、Reaction-Diffusionの世界では、この「2つの物質の終わらない追いかけっこ」の境界線上に、文字通り勝手に浮かび上がってくるのです。

3. GLSLでの実装イメージ(概要だけ)

この「2つの物質の追いかけっこ」を、ピクセルシェーダー(Fragment Shader)の世界でどうやって計算するのでしょうか。

GLSLにおいて、画面に描画される個々のピクセルは、まさにシャーレの上に並んだ「ミクロな細胞のグリッド」そのものです。ここでは、ピクセルの色情報(RGB)を単なる「見た目」としてではなく、「物質の濃度データを保存する配列」としてハックします。 例えば、赤チャンネル(R)に物質 $A$ の濃度(0.0〜1.0)を、緑チャンネル(G)に物質 $B$ の濃度を格納するのです。

シミュレーションの1サイクル(1フレーム)は、以下のようなステップで進みます。

Step 1: 初期状態のセットアップ(種の投下)

シミュレーションの最初のフレーム($t = 0$)では、画面全体(すべてのピクセル)を物質 $A$ で満たし、濃度を $1.0$ にします。そして、画面の中央など特定の数ピクセルにだけ、少しだけ物質 $B$ を「ポトッ」と落とします(シードの配置)。

Step 2: 周囲のサンプリング(ラプラシアンの計算)

毎フレーム、各ピクセルは自分自身の現在位置の濃度だけでなく、「上下左右、および斜めの隣接ピクセル」の状態を texture2D を使ってサンプリングします。 周囲のピクセルと自分自身の濃度差を計算することで、「周囲から自分のマスへ物質がどれくらい流れ込んでくるか(あるいは流れ出していくか)」を導き出します。これを数学的にはラプラシアン(Laplacian)と呼びます。

Step 3: 反応と拡散の計算、そして更新

取得した周囲の濃度勾配(拡散)と、物質 $A$ と $B$ それぞれの増減ルール(反応)を数式に当てはめ、次の瞬間の濃度を計算します。 導き出された新しい $A$ と $B$ の濃度を、再び gl_FragColor の赤と緑チャンネルに出力して上書きします。

時間の経過(Ping-Pong バッファ)

これを Three.js 側で構築した Ping-Pong バッファ(2枚のテクスチャを交互に読み書きする仕組み)に組み込み、60FPSで高速に回します。

すると、最初は中央に落とされたただの「点」だった物質 $B$ が、ラプラシアンの計算に従ってジワジワと周囲の物質 $A$ を侵食し始めます。やがて細胞分裂のように規則的な広がりを見せ、数秒後には画面全体を覆い尽くす、美しいサンゴ礁や迷路のような模様へと成長していくのです。