![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 (частотную модуляцию). Поздравляю!

Ещё одна интересная особенность волн - это их способность суммироваться, то есть образовывать суперпозицию. Закомментируйте, раскомментируйте и изменяйте параметры в следующих строках. Понаблюдайте как при этом изменяется внешний вид графика суммы волн с различной амплитудой и частотой.

<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>

* Поэксперементируйте с изменением амплитуды и частоты суммируемых волн.
* Можно ли сделать две взаимоуничтожающихся волны? Как это будет выглядеть?
* Можно ли сложить волны таким образом, чтобы они усиливали друг друга?

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

Теперь давайте воспользуемся шумом Перлина вместо синусоидальной волны! Шум Перлина в самой простой форме выглядит и ощущается так же, как синусоидальная волна. Его амплитуда и частота немного плавают, но амплитуда остаётся достаточно однородной, а частота ограничена довольно узким диапазоном вокруг центральной частоты. Поведение этого шума менее предсказуемо, чем синусоидальная волна, а значит с его помощью проще создать иллюзию беспорядка, сложив несколько волн шума с различными параметрами. Сумму синусоидальных волн тоже можно заставить выглядеть беспорядочно, но для этого понадобится очень много волн, чтобы скрыть их периодическую, регулярную природу.

Складывая различные итерации шума (*октавы*), в которых мы последовательн увеличиваем частоту на одну и ту же величину (*лакунарность*) и понижаем амплитуду (*усиление*) шума, можно получить более качественный и детализированный рисунок шума. Эта методика называется «Фрактальным броуновским движением» (*фБД*), или попросту «фрактальным шумом». В простейшем варианте она реализуется следующим кодом:

<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 итераций. Наблюдайте за происходящим.
* При количестве октав больше четырёх попробуйте изменить значение лакунарности.
* Так же, при количестве октав больше четырёх, измените усиление (gain) и посмотрите что произойдёт.

Обратите внимание, как с каждой новой октавой кривая становится более детализированной. Так же обратите внимание на самоподобность, появляющуюся с увеличением количества октав. При увеличении кривой боле мелкие части выглядят почти так же, как и вся кривая, а любой участок кривой выглядит похожим на любой другой участок. Это важное свойство математических фракталов, которое мы симулируем с помощью цикла. Ме не создаём *настоящий* фрактал, потому что мы останавливаем симуляцию после нескольких итераций, но, теоретически, мы могли бы получить настоящий фрактал, если бы позволили циклу крутиться бесконечно долго, складывая бесконечно много компонент шума. В компьютерной графике всегда есть предел того, насколько малые объекты мы можем различить. Например, некоторые детали могут стать меньше размера пикселя, поэтому нет никакого смысла обсчитывать бесконечные суммы для создания математически точного фрактала. Иногда может пригодиться очень много слагаемых, но их никогда не понадобится бесконечно много.

В следующем примере реализовано двумерное фБД, которое создаёт похожее на фрактал изображение:

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

* Уменьшите количество октав, изменив значение в строке 37
* Измените значение лакунарности фБД в строке 47
* Посмотрите что будет при изменении усиления в строке 48

Эта техника обычно используется для создания процедурных ландшафтов. Самоподобность фБД идеальна для создания гор, потому что естественная эрозия, обрабатывающая настоящие горы, создёт самоподобные образы в большом диапазоне масштабов. Если вас это заинтересовало, вам определённо стоит прочитать [замечательную статью Иниго Квилеса о подвинутых способах получения шума](http://www.iquilezles.org/www/articles/morenoise/morenoise.htm).

![ Дэн Холдсворт - блэкаут (2010)](holdsworth.jpg)

Используя этот подход практически в неизменном виде, можно получить много других эффектов, например так называемую **турбулентность**. Это то же самое фБД, составленное из абсолютных величин шума, что добавляет к изображению резкие впадины.

```glsl
for (int i = 0; i < OCTAVES; i++) {
    value += amplitude * abs(snoise(st));
    st *= 2.;
    amplitud *= .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 главе книги Кентона Масгрейва «Текстурирование и моделирование: процедурный подход (третье издание)» (Texturing and Modeling: a Procedural Approach). К несчастью, эту книгу перестали издавать несколько лет назад, но её по прежнему можно найти в библиотеках или на вторичном рынке. В онлайн-магазинах есть PDF-версия первого издания, но я не советую её покупать - это пустая трата денег. Она издана в 1994 году и не содержит ничего о моделировании ландшафтов из третьего издания.

### Искривление областей

[Иниго Квилес написал ещё одну замечательную статью](http://www.iquilezles.org/www/articles/warp/warp.htm) о свёртывании пространства фБД с помощью фБД. Взрыв мозга? Да, это как сон внутри сна в фильме «Начало».

![ Иниго Квилес - f(p) = fbm( p + fbm( p + fbm( p ) ) ) (2002)](quiles.jpg)

Менее экстремальный пример такого подхода реализован в коде ниже, где сворачивание используется для создания текстуры, похожей на облака. Обратите внимание на сохранившееся самоподобие в этом примере.

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

Оборачивание текстурных координат шумом - это весело, полезно и возможно не просто в изучении. Это мощный инструмент, требующий некоторого опыта в использовании. Например, можно смещать координаты на величину производной (градиента) шума. На этой идее основана [знаменитая статья Кена Перлина и Фабриса Нере под названием «Шум потока»](http://evasion.imag.fr/Publications/2001/PN01/). Некоторые современные реализации шума Перлина основаны на вычислении функции и её аналитического градиента. Иногда «настоящий» градиент для процедурной функции вычислить невозможно, но всегда можно вычислить его приближение конечной разностью, хотя результат будет менее точным и потребует больше вычислений.
