Розуміння шуму Перліна


31

Я граю з Перлін Шумом після роботи з Diamond Square. Я слідкував за виконанням Уго Еліасом, який, в основному, робить ряд функцій з x, y як вхідних даних для передачі кожного значення координати.

Мій PHP-код тут :

У мене є два питання:

Як використовувати алгоритм для створення карти висоти в масиві? Я не до кінця зрозумів це і просто переніс на PHP псевдокод, але виконуючи останню функцію (map_perlined) після того, як десь прочитав, що алгоритм "магічно" дає вам перехідні значення для кожного x, y точки (мабуть, не читаючи його суміжні значення), я просто отримую це при використанні як випадкова функціяmt_rand(-100,100)/100;

введіть тут опис зображення

І це при використанні криптографічного: 1.0-(($n*($n*$n*15731+789221)+1376312589)&0x7fffffff)/1073741824.0;(що, BTW, можна реалізувати "як є" в PHP?):

введіть тут опис зображення

Отже, підводячи підсумки, три питання:

  1. Чи правильний мій код?
  2. Випадкова функція може бути перенесена на PHP, як описано в коді? Він не кидає помилок, але результатів немає.
  3. Як я фактично використовую алгоритм?

ОНОВЛЕННЯ

Гаразд, зробив PHP-порт коду, показаного на папері Густавсона, і як сказав інший кодер, він просто генерує одну октаву. Чи є будь-який інший корисний сайт / папір / посібник про те, як використовувати це з поняттями декількох октав, амплітуди, частоти тощо для управління функцією шуму? На роботі Густавсона просто показані результати, а не реальна реалізація алгоритму, можливо, я щось пропускаю?

ОНОВЛЕННЯ 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 я отримую досить тупу карту висоти, наприклад:

введіть тут опис зображення

Як засіяти карту? Можливо, мені потрібно реалізувати 3d версію з третім значенням випадкової висоти? Але якщо так, я повинен був би з'ясувати, щоб взяти до уваги сусідні значення, які я б закінчував чимось на зразок алмазного квадратного алгоритму, саме того, чого я не хочу робити.

ОНОВЛЕННЯ 3

Більше роботи Перліна. Я ще не знайшов способу спрямувати шум на свої результати. Перевірте ці октави та кінцевий результат:

Октава 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); але я потрапив на подібну проблему рідною мовою, коли вперше впроваджував перлін. Також вбивайте октави і просто налагоджуйте один рівень перлін.
Джонатан Дікінсон

Хто-небудь для мого оновлення III?
Габріель А. Зоррілья

Відповіді:


28

Те, що ви реалізували, не є шумом Перліна. Я не впевнений, чому Юго Еліас каже, що це так, але він розгублений. Ось довідкова реалізація Кена Перліна. Він насправді не викликає жодного зовнішнього генератора випадкових чисел, але використовує вбудовану хеш-функцію для створення псевдовипадкових векторів градієнта.

Зауважимо також, що шум Перліна складається всього з однієї октави. Підсумовування декількох октав (масштабовані екземпляри функції шуму), як пропонує Уго Еліас, є корисною технікою, але не є частиною шуму Перліна. Те, що ви отримуєте завдяки цьому, називається фрактальним шумом, іноді "фрактальним броунівським шумом" (через передбачувану подібність броунівського руху).

Якщо ви хочете зрозуміти геометрично, що алгоритм робить, спробуйте цей документ . Йдеться про різний вид шуму, який називається "симплексний шум", але також включає пояснення класичного шуму Перліна. Між іншим, симплексний шум був також винайдений Перліном і, як передбачається, буде покращенням його класичного шуму, тому ви можете спробувати його реалізувати, якщо вам цікаво грати з шумовими функціями.


2
+1 для статті Густавсона. Це пояснює як перлінне, так і симплексний шум найяснішим способом, який я бачив досі. Очевидно симплексні правила шуму!
FxIII

Я також виявив цей папір деякий час тому, але Гюго виглядав простіше. Я прочитаю його і дам йому зняти! Спасибі!
Габріель А. Зоррілла

2
будьте обережні при завантаженні симплексного шуму, у ньому може бути вірус;)
bobobobo

Я знаю, що це стара тема, але сказати, що реалізація посилань не використовує випадкове число, є невірним. При ініціалізації бібліотеки (або вперше викликається функція шуму) генерується 256 випадкових градієнтів. Хеширование, на яке ви посилаєтесь, - це просто примусити нескінченний набір цілих чисел у діапазон [0, 255], який кешується. По суті, це лише оптимізація таблиці пошуку, і алгоритм працює так само добре, якщо, наприклад, ви закладаєте PRNG з координатною сіткою і використовуєте її для створення градієнта, це просто (набагато) повільніше.
bcrist

@bcrist Я думаю, ви маєте на увазі старішу версію шуму Перліна. "Покращений шум" Перліна, з яким я пов'язаний , використовує фіксований набір з 12 градієнтних векторів, а не 256 випадкових. Він використовує таблицю перестановки як хеш-функцію для відображення координат сітки до одного з цих 12 градієнтних векторів.
Натан Рід

11

Це поширена помилка. Те, що Юго Еліас називає «перлінським» шумом, насправді є фрактальним, або рожевим, шумом. Щоб краще зрозуміти, що таке шум Перліна, ви можете прочитати статтю Перліна, пов’язану з відповіддю Натана Ріда, або документи з лібноаз (там така сама помилка: шум Перліна - це те, що вони називають шум градієнта), або документи CoherentNoise .

Тепер, щоб насправді відповісти на ваше запитання: ви не отримали очікуваного результату, оскільки частота шуму занадто висока. Ваші частоти починаються з 1 і збільшуються, тобто кожен піксель на отриманій карті має випадкове значення. Щоб побачити більш точну структуру карти, вам потрібно «збільшити масштаб» шуму. Я не дуже розмовляю PHP, але я думаю, що код повинен виглядати так:

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

Тобто ви "розтягуєте" один період шуму на всій своїй карті. Звичайно, можна використовувати й інші коефіцієнти - просто спробуйте різні, подивіться, що вийде.


Дякуємо за цілісні шумові документи! Я бачу, що ви це написали :) Яка помилка в документах libnoise? Чи не перлінський шум є різновидом градієнтного шуму?
legends2k
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.