[Noise 入門 #17] 4D Voronoi × Simplex Noise — 動く細胞とノイズの融合(Noise Blending)

はじめに

Noise 入門シリーズ第17回。 前回(#16)では、4D Simplex Noise と FBM、Domain Warping を掛け合わせ、「滑らかな流体」である炎やプラズマを錬成しました。

今回は、一度通り過ぎた 「Voronoi / Worley Noise(#12, #13)」 の幾何学的な世界へ再び潜ります。

静止していた Voronoi の細胞(Cell)に「時間(Time)」という第4の次元を与えたら、細胞たちはどう分裂し、蠢き始めるのか? そして、Simplex Noise の「滑らかなうねり」と、Voronoi の「幾何学的な鋭さ(ヒビ割れ)」を混ぜ合わせると、一体どんな未知のキメラ(複合マテリアル)が生まれるのか?

生物的な鼓動と無機物な冷たさが交差する、新たなプロシージャル表現 「Noise Blending(ノイズ同士の融合)」 に挑戦します。

1. 4D Voronoi Noise — 細胞に「時間」を与える

これまでの記事(#12, #13)で実装した Voronoi Noise は、空間をグリッドに分割し、各グリッド内にランダムな「特徴点」を1つ配置して、「ピクセルから一番近い特徴点までの距離」を計算するものでした。 これは結晶やひび割れのような美しい幾何学模様を生み出しますが、完全に静止した世界です。

この細胞たちを“生きている”かのように蠢かせるにはどうすればいいでしょうか? 答えはシンプルです。各グリッド内にある特徴点(Point)の位置を、時間(Time)によって動かしてあげればよいのです。

特徴点を動かす「円軌道」の数式

GLSLでこれを実現するには、ランダムな点の座標を計算する際、三角関数(sincos)と時間 u_time を組み合わせます。

以下が、特徴点をグリッド内で泳がせるための魔法の数式です。

// i_st はグリッドのインデックス(整数座標)
vec2 point = random2(i_st);

// 時間とランダム値を使って特徴点を動かす
point = 0.5 + 0.5 * sin(u_time + 6.2831 * point);

一見すると複雑な式に見えますが、数学的に分解すると非常に理にかなった動きをしています。 この特徴点の位置 $P(t)$ は、以下の式で表されます。

$$P(t) = 0.5 + 0.5 \cdot \sin(t + 2\pi \cdot R)$$

  • $R$ (ランダムな初期値): random2(i_st) で取得した、0.0〜1.0 のランダムなベクトルです。
  • $2\pi \cdot R$ (位相のズレ): 6.2831 は $2\pi$(円周率の2倍)です。これにランダム値を掛けることで、グリッドごとに 0 から の間で「動き出すスタート位置(位相)」をバラバラにします。
  • (時間): u_time が加算されることで、時間が進むにつれて sin の波が進行します。
  • 0.5 倍して 0.5 を足す: sin の出力は -1.0 から 1.0 の範囲ですが、このままでは特徴点が自分のグリッドを大きく飛び出してしまいます。0.5倍して(-0.5 〜 0.5)、さらに0.5を足すことで、出力値を 0.0 から 1.0 の範囲にピタリと収めています。

この計算により、特徴点は「自分のグリッド(1x1の枠内)」という見えない檻の中を、決して外に出ることなく、ランダムな円軌道を描いて永遠に泳ぎ続けることになります。

GLSLでの全体像:3x3の隣接グリッド探索

特徴点が動くということは、ある瞬間に「隣のグリッドにいる特徴点」が、自分自身のグリッドにいる特徴点よりも近づいてくる可能性があるということです。

そのため、静止したVoronoiと同様に、自分の周囲3x3(合計9個)のグリッドを for ループで探索し、常に「現在、一番近い動く点はどれか?」を計算し直す必要があります。

vec2 f_st = fract(st); // グリッド内のローカル座標 (0.0 ~ 1.0)
vec2 i_st = floor(st); // グリッドのインデックス

float min_dist = 1.0; // 最小距離の初期値

// 周囲3x3のグリッドを探索
for (int y = -1; y <= 1; y++) {
    for (int x = -1; x <= 1; x++) {
        vec2 neighbor = vec2(float(x), float(y)); // 隣接グリッドの相対位置
        vec2 point = random2(i_st + neighbor);     // 隣接グリッドのランダムシード

        // 特徴点に時間(u_time)を与えて動かす
        point = 0.5 + 0.5 * sin(u_time + 6.2831 * point);

        // ピクセルから動く特徴点までの距離ベクトル
        vec2 diff = neighbor + point - f_st;
        float dist = length(diff);

        // 最小距離を更新
        min_dist = min(min_dist, dist);
    }
}

生まれる Cellular Dynamics(細胞力学)

このコードをコンパイルした瞬間、画面上の静止していた幾何学模様が、一斉に蠢き始めます。

細胞の核(特徴点)が不規則に泳ぎ回ることで、細胞壁(境界線)がヌルヌルと形を変え、ある細胞は縮んで消滅しそうになり、またある細胞は大きく膨張する、まるで顕微鏡で微生物の分裂・融合を見ているかのような Cellular Dynamics(細胞力学) のアニメーションが生まれます。

この「動く Voronoi」こそが、水面を揺らめく光の網目(コースティクス)や、脈打つ血管、エイリアンの皮膚をプロシージャルに生成するための最強のベース素材となります。

2. Noise Blending — 相反する性質を混ぜ合わせる

動く Voronoi が完成したら、いよいよ今回のメインテーマ 「ノイズの融合(Noise Blending)」 です。

プロシージャル生成において、単一のノイズだけで作られたマテリアルは、どうしても「どこかで見たことのあるCGっぽさ」が抜けません。しかし、全く異なるアルゴリズムを組み合わせることで、単体では絶対に表現できない、自然界の複雑なマテリアルを作り出すことができます。

今回混ぜ合わせる2つの素材の性質を整理しましょう。

  • Simplex Noise: 滑らかさ、有機的なうねり、流体、グラデーション
  • Voronoi Noise: 鋭さ、幾何学、ひび割れ、結晶、明確な境界線

これらをどう混ぜるのか? アプローチは主に2つあります。

アプローチ A:出力値のブレンド(Math Operations)

最もシンプルで直感的な方法は、2つのノイズがそれぞれ計算した「最終的な出力値(0.0〜1.0のスカラー値)」を、数学的に混ぜ合わせることです。Photoshop のレイヤーのブレンドモード(描画モード)を想像すると分かりやすいでしょう。

  • 乗算(Multiply): simplex * voronoi Voronoi が描くシャープなヒビ割れに対して、Simplex を「マスク(濃淡のフィルター)」として掛け合わせます。これにより、ヒビ割れが一部では深くクッキリと現れ、別の場所では薄く消えかかるような、「風化して苔むした岩肌」 や 「部分的に乾いた泥の地面」 を表現できます。
  • 加算(Add)/ 減算(Subtract): Voronoi の細胞(ベースの形)の上に、Simplex の細かな凹凸(ディテール)を加算します。細胞一つ一つがザラザラとした質感を持つようになり、「ゴツゴツした爬虫類の鱗」 や 「表面が荒れた隕石」 を作るのに最適です。
  • 線形補間(Mix): mix(voronoi, simplex, mask) 第3のノイズやパラメータをマスクとして使い、ある領域はVoronoi、ある領域はSimplexと、空間的にキッパリと切り替える手法です。
// アプローチAのGLSL例
float s = snoise(uv * 3.0); // 滑らかなうねり
float v = voronoi(uv * 5.0); // 鋭い細胞

// 乗算でブレンド(Simplexをマスクにする)
float rock_texture = v * s;

アプローチ B:座標系のブレンド(Domain Warpingの応用)

アプローチ A が「結果」を混ぜるものだとしたら、こちらは「前提」を捻じ曲げる手法です。これこそが、現在のプロシージャル表現における“神領域”のアプローチと言えます。

Voronoi を計算するための「入力座標(UV)」を、そのまま渡すのではなく、先に Simplex Noise の波を使って歪ませて(Warping して)しまいます。

// UV空間をSimplexで滑らかに歪ませる
// strength で歪みの強さを制御
float strength = 0.2;
vec2 warpedUV = uv + snoise(uv * frequency + u_time) * strength;

// 歪んだUVを使って、Voronoiを計算する
float v = voronoi(warpedUV);

なぜこれが「神領域」なのか?

通常の Voronoi Noise の細胞壁(境界線)は、数学的に定義された「直線」で構成されています。しかし自然界において、完全な直線はほとんど存在しません。

座標空間自体が Simplex の波でグニャグニャに歪んでいる(Warping)ため、その歪んだ空間の上で Voronoi を計算すると、本来「直線」になるはずだった細胞壁が、有機的に湾曲し、引き伸ばされ、ちぎれるように変形します。

「幾何学的な規則性」というベースがありながら、その上に「流体力学的なカオス」が乗っかることで、水面に反射する光の網目(コースティクス)や、マグマの対流、エイリアンの皮膚のような、「規則性があるのに崩れている」という極めて自然界に近いカオスが生まれるのです。

3. 生み出される未知のキメラたち

この「4D Voronoi × Simplex の Domain Warping」という強力な武器を駆使すると、単一のノイズでは到達できなかった、複雑で説得力のあるマテリアル(魔法)を Shader 上に具現化できます。

具体的にどのような表現が可能になるのか、いくつか代表的な「キメラ」のレシピを見ていきましょう。

脈打つマグマのヒビ(Lava Fissures)

大地を引き裂くような鋭いヒビ割れと、その奥でドロドロと流れる高熱のマグマ。

  • レシピ: まず、ベースとなる地形の「鋭いヒビ」を作るために、Voronoi の F2 - F1(2番目に近い点との距離 - 1番目に近い点との距離)を用いて境界線を抽出します。ただし、この時の UV 座標は事前に Simplex Noise で歪ませて(Warping して)おきます。これにより、直線的だったヒビが自然な岩肌のようにギザギザに割れます。 そして、そのヒビの谷底(値が0に近い部分)に対して、別の動く Simplex Noise をマスクとして掛け合わせ、赤から黄色に変化する炎のグラデーション(Color Ramp)を流し込みます。冷えた岩石と、脈打つ熱量という相反する要素が共存するマテリアルが完成します。

異星の生体組織(Alien Biomass)

映画やゲームに登場する、呼吸しているかのように蠢くエイリアンの卵や、謎の肉塊。

  • レシピ: 細胞が蠢く 4D Voronoi をベースにします。ここに、非常に振幅の大きい(strengthの強い)低周波の Simplex Noise で強烈な Domain Warping をかけます。細胞壁が極限まで引き伸ばされ、ちぎれそうになるほど歪みます。 さらに、UV 全体のスケール(縮尺)に対して、ゆっくりとした sin(u_time) を掛け合わせることで、マテリアル全体が「ズズゥ…」と膨張と収縮を繰り返す“呼吸”の表現を加えます。幾何学が完全に崩壊し、不気味な生命感を帯びたテクスチャの誕生です。

水底の揺らめき(Caustics / コースティクス)

プールの底や浅瀬で、太陽の光が水面の波に屈折して描く、あの美しい光の網目模様。

  • レシピ: 実は、あの光の集束(コースティクス)の数学的性質は Voronoi に非常に近いです。時間を少し早めに設定した 4D Voronoi を生成します。この時、光の線を鋭く飛ばすために、Voronoi の出力結果に対して pow(v, 4.0) のように累乗をかけてコントラストを極端に上げます。 そして、この光の網目を、「ゆっくりと動く Simplex Noise」 で Warping します。水面(Simplex の波)によって光の屈折先(Voronoi の座標)が歪められる、という物理現象をそのまま Shader で模倣するのです。最後に透き通るようなシアンとブルーを乗せれば、息を呑むような水底の風景が広がります。

錬金術のフェーズへ

もはや、「ただノイズ関数を呼び出して白黒の模様を出す」だけの時代は終わりました。

  • どのノイズで基礎構造を作るか?
  • どのノイズで空間(座標)をねじ曲げるか?
  • 時間の流れ(スピード)をどう変えるか?
  • そして、どう色(光)を乗せるか?

これらを組み合わせるプロセスは、まるで未知の素材を大釜に放り込んで新しい魔法薬を調合する「錬金術」そのものです。Noise Blending を手に入れたあなたは、想像しうるほぼすべての自然物や魔法エフェクトの“質感”を、数学の力だけで創り出せるようになったのです。

まとめ

今回の「Noise Blending」の探求を通して、私たちは以下の強力な錬金術を手に入れました。

  • Cellular Dynamics(細胞力学): Voronoi の特徴点に sin(u_time) を与えることで、静止した幾何学が蠢き出すアニメーションへ進化する。
  • 未知のマテリアル錬成: 性質の違うノイズ(流体的な Simplex と、幾何学的な Voronoi)を掛け合わせることで、単体では絶対に不可能な複雑な質感(キメラ)を生み出せる。
  • 究極の武器「Domain Warping」: 単に結果を混ぜるのではなく、「Simplex で座標空間を歪ませてから Voronoi を計算する」 アプローチは、プロシージャル表現における最強の武器の一つ。

無機質な数学と幾何学で構成されたノイズが、ブレンドと時間の魔法によって、確かな「生命感」を獲得する瞬間を体感できたはずです。

次回予告:Procedural Texture の極北 — 法線(Normal)の捏造とライティング

異なるノイズを混ぜ合わせることで、極めて美しく複雑なマテリアルを作り出すことができました。しかし、今のままでは画面に張り付いた「ただの平坦な模様」に過ぎません。

この模様を、本当に光を反射し、影を落とす 「立体的な質感(3Dマテリアル)」 に昇華させるにはどうすればいいのでしょうか?

次回(#18)は、ノイズの勾配(Gradient)から法線マップ(Normal Map)をリアルタイムに計算・捏造し、Shader内で光と影をシミュレーションする「Procedural Lighting」の世界へ足を踏み入れます。

ピクセルの色が単なる模様から脱却し、ノイズが真に「触れられそうな物質」へと変わる瞬間をお見せします。お楽しみに!