パーリンノイズ:プロシージャル生成を美しくしたアルゴリズム
パーリンノイズアルゴリズムの深掘り:コヒーレントノイズの基礎から勾配ベクトルと順列テーブルの実装詳細まで。
プロシージャル生成はノイズなしでは成り立たず、最も有名なノイズ関数がパーリンノイズだ。この記事では、ノイズ関数の基本概念から完全な実装まで、アルゴリズムを段階的に解説する。
ノイズとは何か
ノイズの本質は、ランダムな値の集合である。つまり、N個のパラメータを受け取り、ある規則に従って値を返す関数だ。2Dノイズの場合、グレースケールテクスチャとして視覚化できる。各ピクセルの明るさが、その座標におけるノイズ値に対応する。
単純なランダム関数(rand(x + y)など)を使う単純なアプローチは、ホワイトノイズを生成する。すべてのピクセルが独立しており、識別可能なパターンはない。これは地形、雲、テクスチャの生成にはあまり役立たない。
コヒーレントノイズ
実際に必要なのはコヒーレントノイズであり、これには3つの特性がある:
- 同じ入力は常に同じ出力を返す
- 入力の小さな変化は出力の小さな変化を生む
- 入力の大きな変化は出力のランダムな変化を生む
これにより、全体的にはランダムでありながら、滑らかで有機的なパターンが得られる。
パーリンのアルゴリズム
ケン・パーリンは1983年、ディズニーの『トロン』の作業中にこのアルゴリズムを開発した。CGIの機械的な見た目に不満を感じたためだ。1997年にはアカデミー賞を受賞している。
核となるアイデア:2D平面上の任意の点について、その点が含まれる正方形の4つの整数コーナーを見つける。各コーナーには、事前に計算されたランダムな単位ベクトル(勾配)がある。各コーナーから点へのベクトルを計算し、各ペアのドット積を取り、4つのドット積を補間する。
勾配と順列テーブル
無限の勾配を事前計算できないため、パーリンは固定された256個のランダム単位ベクトルと256要素の順列テーブルを使用する。順列テーブルはフィッシャー・イェーツ方式のスワップでシャッフルされ、バッファオーバーフローを避けるために512エントリに複製される。
セットアップコードは以下の通り:
for (int i = 0; i < B; i++) {
permutation[i] = i;
gradients[i] = Vector2.Random();
gradients[i] = Vector2.Normalize(gradients[i]);
}
for (int i = 0, j = 0; i < B; i++) {
int k = permutation[i];
permutation[i] = permutation[j = random() % B];
permutation[j] = k;
}
for (i = 0; i < B + 2; i++) {
permutation[B + i] = permutation[i];
gradients[B + i] = gradients[i];
}ここでBは256である。順列テーブルにより、ノイズは決定論的でありながら一見ランダムになる。同じ整数座標は常に同じ勾配にマッピングされるが、隣接する座標は異なる勾配を得る。
ノイズ値の計算
与えられた点(x, y)について、4つのコーナーへの相対ベクトルを計算し、順列テーブルを介して勾配を検索する。次にドット積を取り、スムーズステップ関数(通常6t⁵ - 15t⁴ + 10t³)を使用して補間し、目に見えるグリッドアーティファクトを回避する。
オリジナルの実装では、座標をラップするために255とのビット単位ANDを使用する。これは実質的にモジュロ演算であり、ノイズを256単位ごとに周期的にする。これが実用的な制限である。その範囲を超えるとパターンが繰り返される。
ケン・パーリンは1983年、当時のコンピュータ生成画像の「機械的な」見た目に不満を感じ、パーリンノイズを開発した。