パーリンノイズについて


31

私は、Diamond Squareでの仕事の後、Perlin Noiseをいじっています。基本的に、各座標値をスローするための入力としてx、yを使用して一連の関数を作成するHugo Elias実装に従いました。

私のPHPコードはこちらです

2つの質問があります。

アルゴリズムを使用して、配列に高さマップを生成するにはどうすればよいですか?私はそれを完全には理解せず、PHPに擬似コードを移植しましたが、アルゴリズムが「魔法のように」与えられたx、yポイントごとに遷移した値を与えることを読んだ後、最後の関数(map_perlined)を実行します(明らかに、隣接する値)、ランダム関数として使用するときにこれを取得しますmt_rand(-100,100)/100;

ここに画像の説明を入力してください

そして、これは暗号を使用する場合:(1.0-(($n*($n*$n*15731+789221)+1376312589)&0x7fffffff)/1073741824.0;ところで、これはPHPに「そのまま」実装できますか?):

ここに画像の説明を入力してください

要約すると、3つの質問:

  1. 私のコードは正しいですか?
  2. ランダム関数は、コードで説明されているようにPHPに移植できますか?エラーはスローされませんが、結果はそこにありません。
  3. アルゴリズムを実際に使用するにはどうすればよいですか?

更新

OK、Gustavsonの論文に示されているコードのPHPポートを作成しました。他のコーダーが言ったように、1オクターブを生成するだけです。複数のオクターブ、振幅、周波数などの概念でこれを使用してノイズ機能を制御する方法について、他の有用なサイト/ペーパー/ガイドがありますか?Gustavsonの論文では、アルゴリズムの実際の実装ではなく、結果のみを示していますが、おそらく何かが欠けていますか?

更新2
@NATHAN

私は次のようなものを作りました:

$persistence = 0.5;

for ($j = 0; $j < $size; $j++) {
    for ($i = 0; $i < $size; $i++) {

        for ($o = 0; $o < 8; $o++) {
            $frequency = pow(2,$o);
            $amplitude = pow($persistence, $o);
            $value += SimplexNoise($i*$frequency, $j * $frequency) * $amplitude;
            }

            //$value = SimplexNoise($i, $j) + 0.5 * SimplexNoise($i, $j) + 0.25 * SimplexNoise($i, $j);
            $this->mapArray[$i][$j] = new Cell($value);

そして、値を0..1に正規化した後、次のようなやや鈍い高さマップを取得します。

ここに画像の説明を入力してください

マップをシードするにはどうすればよいですか?おそらく私が実装する必要があるのは、3番目の値がランダムな高さの3Dバージョンですか?しかし、もしそうなら、私は隣人の値を考慮するために見つけなければなりません、それは私がしたくないことを正確にダイアモンドスクエアアルゴリズムのようなもので終わるでしょう。

更新3

より多くのPerlinの仕事。結果にノイズを導く方法をまだ見つけていません。これらのオクターブと最終結果を確認してください。

オクターブIからIV

オクターブ1オクターブ2オクターブ3オクターブ4

要約する

オクターブ1〜4を合計

各オクターブはほぼ同じです。コードを確認してください:

$persistence = 0.5;

    for ($j = 0; $j < $size; $j++) {
      for ($i = 0; $i < $size; $i++) {
        $value = 0;

        for ($o = 0; $o < 4; $o++) {
          $frequency = pow(2,$o);
          $amplitude = pow($persistence, $o);
          $value += improved_noise($i*$frequency, $j*$frequency, 0.5)*$amplitude;

        }
        $this->map[$i][$j] = new Cell($value);

結果は正規化されます。ノイズの発生に強い影響を与えるものは何ですか?振幅を変更すると、ソフトまたは粗い表面が得られる例がありますが、大きな振幅を与えても、ほとんど違いはありません。


perlin(x)+ 0.5 * perlin(2 * x)+ 0.25 * perlin(4 * x)+ ...(オクターブと同じくらいあなたが望む)。また、異なる外観を得るために要因を変更してみることができます。彼らは2のべき乗である必要はありません
ネイサン・リード

1
更新後、Yを正しくスケーリングしていないようです-PHPを理解するのに疲れすぎています(PHPを知らないため)。しかし、perlinを初めて実装するときに、母国語で同様の問題にぶつかりました。また、オクターブを強制終了し、perlinの1レベルをデバッグするだけです。
ジョナサンディキンソン

私のIIIアップデートの誰か?
ガブリエルA.ゾリラ

回答:


28

実装したのは、Perlinノイズではありません。ヒューゴ・エリアスがそう言っている理由はわかりませんが、彼は混乱しています。 ここではケン・パーリンのリファレンス実装です。実際には外部の乱数ジェネレーターを呼び出しませんが、組み込みのハッシュ関数を使用して、疑似乱数勾配ベクトルを生成します。

また、Perlinノイズは1オクターブのみで構成されていることに注意してください。Hugo Eliasが示唆するように、複数のオクターブ(ノイズ関数のスケーリングされたインスタンス)を合計することは便利な手法ですが、Perlinノイズの一部ではありません。これを行うことで得られるものは、フラクタルノイズと呼ばれ、「フラクタルブラウンノイズ」と呼ばれることもあります(ブラウン運動に類似しているため)。

アルゴリズムが何をしているのかを幾何学的に理解したい場合は、このペーパーを試してください。「シンプレックスノイズ」と呼ばれる異なる種類のノイズについてですが、古典的なパーリンノイズの説明も含まれています。ちなみに、シンプレックスノイズもPerlinによって発明されたものであり、彼の古典的なノイズを改善することになっています。


2
Gustavsonの論文の+1。これまで見てきた中で最も明確な方法で、パーリンとシンプレックスノイズの両方を説明します。明らかにシンプレックスノイズルール!
FxIII

私も少し前にその論文を見つけましたが、Hugoの論文はもっとシンプルに見えました。私はそれを読んで試してみます!ありがとう!
ガブリエルA.ゾリラ

2
シンプレックスノイズをダウンロードするときは注意してください、ウイルスがある可能性があります;)
bobobobo

私はこれが古いトピックであることを知っていますが、リファレンス実装が乱数を使用しないと言っているのは間違っています。ライブラリが初期化されるとき(またはノイズ関数が最初に呼び出されるとき)、256個のランダムな勾配が生成されます。参照するハッシュは、整数の無限のセットをキャッシュされている[0、255]の範囲に強制することです。基本的にこれは単なるルックアップテーブルの最適化であり、たとえば、グリッド座標でPRNGをシードし、それを使用して勾配を生成する場合、アルゴリズムは同様に機能します。
bcrist 14年

@bcrist古いバージョンのPerlinノイズについて言及していると思います。私がリンクした Perlinの「改善されたノイズ」は、256個のランダムなベクトルではなく、12個の勾配ベクトルの固定セットを使用します。並べ替えテーブルをハッシュ関数として使用して、グリッド座標をこれらの12の勾配ベクトルのいずれかにマッピングします。
ネイサンリード

11

それはよくある誤解です。ヒューゴエリアスが「パーリン」ノイズと呼ぶものは、実際にはフラクタル、またはピンクのノイズです。Perlinノイズとは何かをよりよく理解するために、Nathan Reedの回答にリンクされているPerlinの記事、またはlibnoise docs(そこに同じエラーがあります:PerlinノイズはGradient noiseと呼ばれます)、またはCoherentNoise docsを読むことができます。

さて、実際にあなたの質問に答えるために:ノイズ周波数が高すぎるため、期待した結果を得られませんでした。周波数は1から始まり、増加します。つまり、結果のマップのすべてのピクセルはランダムな値を持ちます。マップのより細かい構造を見るには、ノイズを「ズームイン」する必要があります。私は実際にはPHPを話せませんが、コードは次のようになっているはずです。

$arrayMap[$i][$j] = PerlinNoise_2D($i/$width, $j/$height, $p, $octaves);

つまり、マップ全体にわたって1周期のノイズを「ストレッチ」します。もちろん、他の係数を使用することもできます-別の係数を試してみて、何が起こるか見てください。


コヒーレントノイズドキュメントをありがとう!あなたはそれを書いたことがわかります:) libnoise docsのエラーは何ですか?パーリンノイズは一種の勾配ノイズではありませんか?
legends2k
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.