2012/06/28

Perlin Noise を実装中

結局、自動生成や様々なシミュレーションの簡易さを考慮し、当面は heightmap からの地形生成のまま進めることにしました。そこで、自分のアプリケーションから heightmap を生成して編集できるようにしようと思い、Perlin noise (パーリン ノイズ) を調べて実装している最中です (過去作成した地形では L3DT で出力した heightmap を利用していました)。

Heightmap や procedural texture を調べると、頻繁に Perlin noise という言葉が出てきます。このため、アルゴリズムの説明や公開コードも豊富であろうと考え、気楽に実装を始めたのですが・・・想定外のハマり方をしました。

結論からは、Perlin noise の説明や実装は簡単に見つかります。しかし、その多くが 「Perlin noise ではない」のです。この答えに到達するまでに随分時間が掛かりました。

Perlin noise は、gradient と呼ばれる擬似乱数のベクトルをグリッド上に配置し、任意の位置 (グリッドに沿っているとは限らない) のノイズ値を、それを取り囲む 4 点にある gradient から重み付けを考えて算出する仕組みかと思います。
恐らく、Perlin noise を理解しようとした場合、Matt Zucker による The Perlin noise math FAQ を読むことがベストだと思います。

Perlin noise は、gradient を元にしたアルゴリズムであることから、gradient noise として分類されるそうです。
Gradient noise: http://en.wikipedia.org/wiki/Gradient_noise
上記ページには、興味深いことが書かれています。「しょっちゅう value noise と混同されます」と。事実、Perlin noise 実装を謳ったコードの多くが、この value noise に分類されるものです。Wikipedia の記述からは、あまりに混同されるために gradient noise と value noise という分類を作ったという印象を受けます。
Value noise: http://en.wikipedia.org/wiki/Value_noise
上記ページには、Perlin noise ではないにもかかわらず Perlin noise として説明している某サイトへのリンクが value noise の説明として貼られています。
厄介なことに、Perlin noise を検索すると、このサイトが上位に現れます。このサイトでは、擬似乱数のスカラー値をグリッド上に配置し、それらにブラーをかけ、更に補間を行ない、滑らかなノイズとしているようです。

このサイトの内容は非常に有益でしたが、誤ったタイトルを付けたことで、Perlin noise ではないものを Perlin noise であると解釈した人が大量に生まれたのではないかと推測します。
僕も Ken Perlin にのみ従っていれば良かったのですが、誰かの C# コード丸パクリで済まそうとしたことで、この混乱の渦へ自ら身を投じてしまったようです。

と言うことで、Ken Perlin によるオリジナル コード、および、 Matt Zucker によるらしい C++ コードを見つけたので (見つけた場所が怪しいためリンクを貼りません) 、それらを元に XNA で実装しています。
先行して、Ken Perlin による Improved Noise reference implementation (Java 実装) を C# へ移植したのですが、ちょっと gradient の式が理解できていません・・・。

他には、libnoise というノイズ生成のためのオープンソース ライブラリも参考にして進めています。libnoise のコードはクラス設計が綺麗に纏められており、コードを読んでいて心地良いです。

0 件のコメント:

コメントを投稿

libgdx いじり

Google が提供している Java 版の Tango Examples は Rajawali をベースにしているため、自分が仕事で開発する Tango アプリも Rajawali ベースとしていましたが、最近は libGDX への移行を進めています。一応、要点については移行が...