パーリンノイズで雲・炎・大理石を描く

なめらかな乱数「パーリンノイズ」を、大きさを変えながら何枚も重ねると、雲や炎、大理石の模様のような自然な形が生まれます。パラメータを動かすと、その場で絵が変わります。

計算はすべてブラウザの中で行います。下の解説では、パーリンノイズの仕組みと、オクターブを重ねた模様(fBm)がフラクタルになる理由を、元の論文をもとに説明します。

プリセット

描き方と色

パラメータ

動かしている間は、端末の処理が重いときに解像度を「低」にするとなめらかになります。画像や設定がサーバーへ送信されることはありません。

パーリンノイズとは

パーリンノイズは、Ken Perlin が考えた「なめらかな乱数」です。ふつうの乱数は、隣り合う点どうしでもまったく関係のない値になるため、画像にすると砂嵐のようになります。パーリンノイズは、近い点では近い値、離れた点では無関係な値になるように作られているので、ゆるやかにうねる模様になります。

Perlin は、映画『トロン』(1982 年)の CG を作った MAGI 社で、システムの設計を担当していました。その後、1983 年にこのノイズを作って使い始め、1985 年の SIGGRAPH で論文「An Image Synthesizer」として発表しました。この論文では、ノイズを組み合わせて、雲・炎・水・星・大理石・木・岩・シャボン膜・結晶の質感を作っています。

この技術は映画の視覚効果で広く使われるようになり、Perlin は 1997 年にアカデミー科学技術賞(Technical Achievement Award)を受けました。受賞理由は、CG の表面に自然な質感を与えるパーリンノイズを開発したことです。

1985 年の論文は、ノイズに次の性質を求めています。

2 つ目の性質が大切です。大きさのそろったノイズを、縮尺を変えて何枚も重ねると、大きな起伏から細かな起伏までを自由に組み立てられます。これが、上のツールで動かしている「オクターブ」の考え方です。

格子と勾配ベクトル

パーリンノイズは、空間を 1 辺 1 の立方体のマス目(格子)に区切り、格子点ごとに決めた勾配ベクトル(どちらへ進むと値が増えるかを表す矢印)から値を作ります。下の図は、3 次元のノイズを平面で切った断面です。

青い線が格子、赤い矢印が格子点ごとの勾配ベクトル(3 次元の勾配の、この断面に沿った成分)です。白い丸の格子点ではノイズの値が 0 になり、矢印の向きに進むほど明るく、逆向きに進むほど暗くなります。

ある点 の値は、次の手順で求めます。

  1. を囲む立方体の 8 つの角(格子点)を見つける。
  2. 角ごとに、その角の勾配ベクトル と、角から へのベクトルの内積 を計算する。角の近くでは、その角の矢印の向きに進むほど値が大きくなる。
  3. 8 つの値を、・・ の順に、後で説明するフェード関数を使って混ぜ合わせる。

格子点そのものでは、角から へのベクトルが 0 なので、値は必ず 0 になります。値の大きい・小さいところは格子点の間に生まれ、格子点の矢印の向きでその形が決まります。格子点ごとに決めた乱数で模様を作るので、同じ格子点には何度計算しても同じ矢印が選ばれ、同じ場所では毎回同じ値になります。

どの格子点にどの矢印を割り当てるかは、0〜255 を並べ替えた表を使って決めます。ツールの「乱数の種」は、この並べ替え方を変えるものです。種を変えると、模様の性質はそのままで、別の模様になります。

1985 年の方式では、球面上にばらまいた 256 本の矢印から選んでいました。2002 年の改良版(Perlin の「Improving Noise」)では、立方体の中心から各辺の中点へ向かう 12 本の矢印 、、 だけを使います。ばらまいた矢印は間隔が不ぞろいで、模様にむらが出ることがありましたが、12 本ならどの 2 本も近づきすぎません。計算が速いことも利点です。このツールは 2002 年の方式で計算しています。

補間とフェード関数

8 つの角の値を混ぜるとき、単純に直線で比例配分(線形補間)すると、マス目の境目で模様が折れ曲がり、格子の形が透けて見えてしまいます。そこで、格子の中の位置 (0〜1)を、両端でなめらかに曲がるフェード関数に通してから混ぜます。

00.250.50.751 00.250.50.751 t(格子の中の位置) 6t⁵ − 15t⁴ + 10t³(2002 年) 3t² − 2t³(1985 年) t(直線でつなぐ場合)
どちらの曲線も、格子点(t = 0 と 1)で傾きが 0 になり、隣の格子とのつなぎ目がなめらかになります。2002 年の曲線は、曲がり具合(2 階の微分)も両端で 0 になります。

元の は、両端で傾き(1 階の微分)は 0 ですが、曲がり具合(2 階の微分)は で 6、 で −6 になり、0 になりません。ノイズを面の凹凸(光の当たり方)に使うと、この不連続が格子の境目の筋として見えてしまいます。2002 年の は、2 階の微分まで両端で 0 になるため、この筋が消えます。

オクターブを重ねる(fBm)

1 枚のパーリンノイズは、どこを見ても同じくらいの大きさの起伏しかありません。自然の雲や山には、大きなうねりの上に小さな凸凹が乗っています。そこで、縮尺を変えたノイズを重ねます。

そのオクターブだけ
1 番目のオクターブ
1 番目(周波数 ×1、振幅 ×1)
2 番目のオクターブ
2 番目(周波数 ×2、振幅 ×0.5)
3 番目のオクターブ
3 番目(周波数 ×4、振幅 ×0.25)
4 番目のオクターブ
4 番目(周波数 ×8、振幅 ×0.125)
5 番目のオクターブ
5 番目(周波数 ×16、振幅 ×0.0625)
1 番目から足したもの
1〜1 番目のオクターブを足した模様
1 オクターブ
1〜2 番目のオクターブを足した模様
2 オクターブ
1〜3 番目のオクターブを足した模様
3 オクターブ
1〜4 番目のオクターブを足した模様
4 オクターブ
1〜5 番目のオクターブを足した模様
5 オクターブ
持続度 0.5・ラクナリティ 2 で、オクターブを 1 つずつ足していった様子です。上段は各オクターブのノイズそのもの、下段はそこまでの合計を青空の色で塗ったものです。

重ねるたびに、模様の細かさ(周波数)を 倍、強さ(振幅)を 倍にします。 枚重ねた値は次の式になります。

1985 年の論文は、周波数を 2 倍ずつ上げながら、振幅を周波数に反比例させて足す(、 にあたる)方法を示しています。論文はこれを「1/f」の信号と呼んでいます。また、重ねる計算を画面の画素の細かさで打ち切ることで、画素より細かい余計な模様が生まれないようにしています。ツールの下に表示している「いちばん細かいオクターブの格子」が 1 画素を下回ると、それ以上オクターブを増やしても、見た目はほとんど変わりません。

このように重ねたものは、fBm(fractional Brownian motion、非整数ブラウン運動)を近似する方法として知られています。F. K. Musgrave は、ラクナリティとオクターブ数に加えて、振幅を「周波数の 乗」に比例させるパラメータ で fBm を表しました(D. S. Ebert ほか『Texturing and Modeling』)。

乱流で大理石と炎を作る

ノイズの値をそのまま重ねる代わりに、絶対値を重ねたものを、Perlin は乱流(turbulence)と呼びました。

絶対値をとると、ノイズが 0 になる線のところで値が鋭く折れ返り、細い筋や渦のような模様になります。ツールで描き方を「乱流」にすると、「fBm」とのちがいがよくわかります。

大理石

1985 年の論文は、大理石を「地層のように重なった縞が、固まる前に乱流でゆがんだもの」と考えました。ゆがむ前の縞は で表せるので、その に乱流を足すだけで大理石の模様になります。

このツールの「大理石」は、縞を少し斜めにし、乱流の効き方を「ゆがみの強さ」 で変えられるようにしています()。ゆがみを 0 にすると、ただの縞模様に戻ります。

炎

論文は、流れの向きがはっきりしているものなら乱流で炎を作れるとして、太陽のコロナを例に挙げています。中心からの距離で色を決め、その距離に乱流を足して形をちぎります。さらに、乱流を調べる位置を時間とともに中心からの向きに沿ってずらし、模様が外へ流れ出すように動かしています。

このツールの「炎」も同じ考え方です。画面の下ほど明るくなる明るさから乱流を引いて縁をちぎり、調べる位置を時間とともに下へずらすことで、模様が上へ昇っていくように見せています。縦に引き伸ばした乱流を使うと、炎の舌のような細長い形になります。

時間で動かす

このツールのアニメーションは、3 次元のノイズの 3 つ目の座標()を時間とともに少しずつ進めて作っています。 が少し変わるだけなら値も少ししか変わらないので、模様がなめらかに変化します。「右へ流れる」「上へ昇る」では、これに加えて調べる位置を一方向にずらしています。

フラクタル次元との関係

fBm では、振幅が「周波数の 乗」に比例します。ラクナリティ で周波数が 倍になるたびに振幅が 倍になるので、、つまり次のように持続度とラクナリティから (ハースト指数)が決まります。

の fBm の曲面は、フラクタル次元が になることが知られています(K. Falconer『Fractal Geometry』)。持続度を上げるほど が小さくなり、次元は 3 に近づきます。よく使われる 、 では で、理想的な fBm としては次元 2(なめらかな面)の境目にあたります。

ただし、パーリンノイズを重ねた模様は、理想的な fBm そのものではありません。オクターブの数が有限なので、いちばん大きい格子より大きな起伏と、いちばん細かい格子より細かい起伏はありません。実際に、ツールと同じ計算で作った模様(8 オクターブ)を、このサイトの画像のフラクタル次元を測るツールと同じ計算で測ると、次のようになりました。

fBm(1024×1024 画素、スケール 4、8 オクターブ、ラクナリティ 2、乱数の種 1)を、/dimension/ と同じ計算(コントラスト正規化あり)で測った値。
持続度 pH = −log p / log 23 − HDBCマドグラム法
0.51.0002.0002.0672.066
0.60.7372.2632.1752.171
0.70.5152.4852.2892.266
0.80.3222.6782.3972.337

持続度を上げるほど、測った次元は大きくなりますが、どの値も より低く出ます。重ねる枚数が限られていることに加えて、差分ボックスカウント法には粗い面ほど値が低めに出る性質があります(/dimension/ の解説を参照)。上のツールの「この模様のフラクタル次元を測る」ボタンを押すと、いま表示している模様を、そのまま測定ページで測れます。

プリセットの作り方

ツールのプリセットは、次の設定で作っています。気に入った模様ができたら、「この設定の URL をコピー」で、設定ごと保存・共有できます。

プリセット描き方スケールオクターブ持続度ラクナリティゆがみ色
雲fBm370.552.000青空と雲
炎炎460.552.002.5炎
大理石大理石260.502.004大理石
木目木目230.502.001.5木
地形fBm2.580.502.000地形(海と陸)
オーロラ乱流250.452.200オーロラ

よくある質問

パーリンノイズと、ふつうの乱数は何がちがうのですか?

ふつうの乱数は、隣り合う点どうしでも無関係な値になるので、画像にすると砂嵐のようになります。パーリンノイズは、格子点ごとに決めた勾配ベクトルをなめらかにつないで作るので、近い点では近い値になり、ゆるやかにうねる模様になります。

同じ設定なら、いつも同じ模様になりますか?

なります。模様は乱数の種と各パラメータだけで決まり、同じ種・同じパラメータ・同じ時刻なら、何度描いても同じ絵になります。「この設定の URL をコピー」で保存した URL を開くと、同じ模様を再現できます(アニメーションの時刻は最初に戻ります)。

オクターブ数を増やしても、模様が変わらなくなるのはなぜですか?

オクターブを 1 つ増やすたびに模様は細かくなり、いずれ 1 画素より細かくなります。画素より細かい模様は画面に表せないので、それ以上増やしても見た目はほとんど変わりません。ツールの下に、いちばん細かいオクターブの格子が何画素になっているかを表示しています。

持続度とラクナリティは、どう使い分ければよいですか?

ラクナリティは「次のオクターブを何倍細かくするか」、持続度は「次のオクターブを何倍の強さで足すか」です。ラクナリティ 2・持続度 0.5 から始め、ざらざらした質感にしたいときは持続度を上げ、なめらかにしたいときは下げると、変化がわかりやすくなります。

パーリンノイズはフラクタルですか?

1 枚のパーリンノイズは、模様の大きさがある範囲に収まっているので、フラクタルではありません。縮尺を変えて何枚も重ねた fBm は、大きな起伏から細かな起伏までが同じ割合で含まれるので、重ねた範囲の中ではフラクタルに近い性質を持ちます。持続度 とラクナリティ から、fBm のハースト指数 が決まります。

アニメーションが重いときは、どうすればよいですか?

1 コマごとに、画素の数 × オクターブ数の回数だけノイズを計算しています。解像度を「低」にするか、オクターブ数を減らすと軽くなります。止めた状態でパラメータを調整し、最後に「PNG で保存」で 1024×1024 の画像にすることもできます。画像はブラウザの中で作られ、サーバーには送信されません。

参考文献