![Due East over Shadequarter Mountain - Matthew Rangel (2005) ](rangel.jpg)

## Фрактальний броунівський рух

Для різних людей слово "шум" означає різні речі. Музиканти будуть думати про безладні звуки, інженери зв'язку — про перешкоди, а астрофізики — про космічний мікрохвильовий фон. Ці концепції повертають нас до фізичної природи випадковості в навколишньому світі. Однак почнімо з чогось більш фундаментального та простішого: хвиль та їхніх характеристик. Хвиля — це коливання певної властивості з плином часу. Аудіохвилі — це коливання тиску повітря, електромагнітні хвилі — це коливання електричного та магнітного полів. Двома важливими характеристиками хвилі є її амплітуда та частота. Рівняння для простої лінійної (одномірної) хвилі виглядає так:

<div class="simpleFunction" data="
float amplitude = 1.;
float frequency = 1.;
y = amplitude * sin(x * frequency);
"></div>

* Спробуйте змінити значення частоти та амплітуди, щоб зрозуміти їх поведінку.
* Використовуючи формотворчі функції, змінюйте амплітуду залежно від часу.
* Використовуючи формотворчі функції, змінюйте частоту залежно від часу.

Виконуючи останні дві вправи, ви "модулювали" синусоїду, створивши AM (амплітудно-модульовані) та FM (frequency modulated - частотно-модульовані) хвилі. Мої вітання!

Ще однією цікавою властивістю хвиль є здатність до їх поєднання, що формально називається суперпозицією. Закоментуйте, розкоментуйте та позмінюйте наступні рядки. Зверніть увагу на зміни загального вигляду, коли ми додаємо разом хвилі з різними амплітудами та частотами.

<div class="simpleFunction" data="
float amplitude = 1.;
float frequency = 1.;
y = sin(x * frequency);
float t = 0.01 * (-u_time * 130.0);
y += sin(x * frequency * 2.1 + t) * 4.5;
y += sin(x * frequency * 1.72 + t * 1.121) * 4.0;
y += sin(x * frequency * 2.221 + t * 0.437) * 5.0;
y += sin(x * frequency * 3.1122 + t * 4.269) * 2.5;
y *= amplitude * 0.06;
"></div>

* Поекспериментуйте, змінюючи частоту й амплітуду додаткових хвиль.
* Чи можна зробити дві хвилі, що нейтралізуватимуть одна одну? Як це буде виглядати?
* Чи можна скласти хвилі так, щоб вони посилювали одна одну?

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

Тепер, замість синусоїди, використаємо шум Перліна! Шум Перліна у своїй основній формі виглядає та відчувається, як синусоїда. Його амплітуда та частота дещо мінливі, але амплітуда залишається досить однорідною, а частота обмежена досить вузьким діапазоном навколо центральної частоти. В цілому шум не такий регулярний, як синусоїда, та з його допомогою легше створити видимість випадковості, об'єднавши кілька масштабованих версій. Вигляд суми синусоїд також можна зробити більш випадковим, але для цього потрібно багато різних хвиль, щоб приховати їх періодичну та регулярну природу.

Додаючи різні ітерації шуму (*октави*), у яких ми послідовно збільшуємо частоту на регулярну величину (*лакунарність*) та зменшуємо амплітуду (*посилення*) **шуму**, можна отримати деталізованіший шум та більше дрібних деталей. Ця техніка називається "фрактальний броунівський рух" (*fBM*) або просто "фрактальний шум". У найпростішому вигляді її можна створити за допомогою наступного коду:

<div class="simpleFunction" data="// Властивості
const int octaves = 1;   // октави
float lacunarity = 2.0;  // лакунарність
float gain = 0.5;        // посилення
//
// Початкові значення
float amplitude = 0.5;
float frequency = 1.;
//
// Цикл по октавам
for (int i = 0; i < octaves; i++) {
&#9;y += amplitude * noise(frequency * x);
&#9;frequency *= lacunarity;
&#9;amplitude *= gain;
}"></div>

* Поступово збільшуйте кількість октав від 1 до 2, 4, 8 і 10. Спостерігайте за результатом.
* Коли матимете понад чотири октави, спробуйте змінити значення лакунарності.
* Також, коли октав понад 4, змініть значення для посилення (gain) та подивіться, що станеться.

Зверніть увагу, що з кожною додатковою октавою крива стає деталізованішою. Також зверніть увагу на прояви самоподібності, зі збільшенням кількості октав. Якщо збільшити масштаб кривої, менша її частина виглядатиме приблизно так само, як і вся крива, а кожен окремий відрізок виглядає більш-менш схоже на будь-який інший. Це важлива властивість математичних фракталів, яку ми моделюємо у нашому циклі. Ми не створюємо *справжній* фрактал, оскільки зупиняємо модуляцію після кількох ітерацій, але теоретично можна отримати справжній математичний фрактал, якщо дозволити циклу тривати вічно та додавати нескінченну кількість компонентів шуму. У комп'ютерній графіці ми завжди маємо обмеження щодо найдрібніших деталей, які можемо розпізнати. Наприклад, якщо об'єкти стають меншими за піксель, немає потреби робити нескінченні обрахунки, щоб створити видимість фракталу. Іноді може знадобитися багато доданків, але ніколи не знадобиться їх нескінченна кількість.

Наступний код показує реалізацію двомірного fBm, схожого на фрактальний візерунок:

<div class="codeAndCanvas" data="2d-fbm.frag"></div>

* Знизьте кількість октав, змінивши значення в рядку 37
* Змініть значення лакунарності у рядку 47
* Дослідіть результати, змінюючи значення підсилення в рядку 48

Ця техніка зазвичай використовується для побудови процедурних ландшафтів. Самоподібність fBm ідеально підходить для створення гір, тому що процеси ерозії, які створюють реальні гори, також надають їм вигляд самоподібності в широкому діапазоні масштабів. Якщо це вас зацікавило, вам варто прочитати [цю чудову статтю Inigo Quiles про вдосконалений шум](http://www.iquilezles.org/www/articles/morenoise/morenoise.htm).

![Blackout - Dan Holdsworth (2010)](holdsworth.jpg)

Використовуючи більш-менш таку саму техніку, можна також отримати й інші ефекти, такі як **турбулентність**. По суті, це fBm, але побудований з абсолютних значень шуму, що створює різкі впадини.

```glsl
for (int i = 0; i < OCTAVES; i++) {
    value += amplitude * abs(snoise(st));
    st *= 2.;
    amplitude *= .5;
}
```

<a href="../edit.php#13/turbulence.frag"><img src="turbulence-long.png" width="520px" height="200px"></img></a>

Іншим представником цього сімейства алгоритмів є **хребти**, де гострі долини перевернуті догори дном, щоб натомість вийшли гострі гребні:

```glsl
    n = abs(n);     // створюємо складки 
    n = offset - n; // інвертуємо складки догори дном
    n = n * n;      // загострюємо складки ще більше
```

<a href="../edit.php#13/ridge.frag"><img src="ridge-long.png"  width="520px" height="200px"></img></a>

Ще один варіант з корисними варіаціями можна здобути за допомогою перемноження компонентів шуму замість їх додавання. Також цікаво масштабувати наступні шумові функції на основі чогось, що залежить від попередніх сум складових. Коли ми робимо подібні речі, то віддаляємося від суворого визначення фракталу та переходимо у відносно невідому область "мультифракталів". Мультифрактали поки що не мають чіткого математичного визначення, але це не робить їх менш корисними для графіки. Насправді мультифрактальне моделювання дуже поширене в сучасному комерційному програмному забезпеченні для генерації рельєфу. Детальніше про це можна прочитати у 16 розділі 3-го видання книги "Текстурування та моделювання: процедурний підхід" ("Texturing and Modeling: a Procedural Approach"), автор Kenton Musgrave. На жаль, цю книгу перестали друкувати, але її все ще можна знайти в бібліотеках та вторинному ринку. Майте на увазі, що в інтернеті продається PDF-версія 1-го видання, яку не варто купувати, оскільки воно не містить жодного матеріалу про моделювання ландшафтів.

### Викривлення домену (просторової області)

[Inigo Quiles написав ще одну захопливу статтю](http://www.iquilezles.org/www/articles/warp/warp.htm) про використання fBm для деформації простору fBm. Вибух мозку, правда? Це як сон уві сні у фільмі "Початок" (Inception).

![f(p) = fbm(p + fbm(p + fbm(p))) - Inigo Quiles (2002)](quiles.jpg)

Менш екстремальний приклад цієї техніки показано у наступному коді, де викривлення використовується для отримання текстури, схожої на хмари. Зверніть увагу, що властивість самоподібності все ще присутня у результаті:

<div class="codeAndCanvas" data="clouds.frag"></div>

Викривлення координат текстури за допомогою шуму може бути дуже корисним, дуже веселим та диявольськи складним для освоєння. Це потужний інструмент, але щоб добре його використовувати, потрібен певний досвід. Корисним підходом для подібних маніпуляцій є зміщення координат за допомогою похідної (градієнта) шуму. На цій ідеї базується відома стаття під назвою ["Шум потоку"](http://evasion.imag.fr/Publications/2001/PN01/), автори Ken Perlin та Fabrice Neyret. Деякі сучасні реалізації шуму Перліна включають обчислення як функції, так і її аналітичного градієнта.
