mirror of
https://github.com/patriciogonzalezvivo/thebookofshaders
synced 2024-11-08 01:10:27 +00:00
93 lines
12 KiB
Markdown
93 lines
12 KiB
Markdown
|
# Генеративный дизайн
|
|||
|
|
|||
|
Не удивительно, что после стольких повторений и порядка, автор вынужден привнести немного хаоса.
|
|||
|
|
|||
|
## Случайность
|
|||
|
|
|||
|
[![Рёдзи Икеда - тестовый шаблон (2008) ](ryoji-ikeda.jpg) ](http://www.ryojiikeda.com/project/testpattern/#testpattern_live_set)
|
|||
|
|
|||
|
Случайность есть сильнейшее проявление энтропии. Но как получить случайность в казалось бы предсказуемом и строгом программном окружении?
|
|||
|
|
|||
|
Давайте начнём со следующей функции:
|
|||
|
|
|||
|
<div class="simpleFunction" data="y = fract(sin(x)*1.0);"></div>
|
|||
|
|
|||
|
Выше мы извлекаем дробную часть синусоиды. Таким образом, значения синуса, плавно изменяющиеся от ```-1.0``` до ```1.0```, урезается до положительного диапазона от ```0.0``` до ```1.0```. Этот эффект можно использовать для получения псевдослучайных значений, "разбивая" синусоиду на меньшие кусочки. Как? Умножением значения синуса на большие числа. Попробуйте добавить нулей в функцию выше.
|
|||
|
|
|||
|
Когда коэффициент достигнет ```100000.0``` (то есть когда функция примет вид ```y = fract(sin(x)*100000.0)```), волны синусоиды станут неразличимыми. Дискретность дробной части повредила плавное течение синусоидальной волны, превратив её в псевдослучайный хаос.
|
|||
|
|
|||
|
## Управление хаосом
|
|||
|
|
|||
|
Использование случайности может стать непростой задачей. Она одновременно бывает слишком хаотичной и не слишком случайной. Посмотрите на следующий график. В нём мы используем функцию rand(), реализованную в точности как показано выше.
|
|||
|
|
|||
|
Присмотревшись, можно увидеть гребень синусоидальной волны в точках ```-1.5707``` и ```1.5707```. Легко понять почему: именно в этих точках синус достигает максимума и минимума.
|
|||
|
|
|||
|
Так же при детальном рассмотрении видно, что значения больше концентрируются в середине, чем на краях полосы.
|
|||
|
|
|||
|
<div class="simpleFunction" data="y = rand(x);
|
|||
|
//y = rand(x)*rand(x);
|
|||
|
//y = sqrt(rand(x));
|
|||
|
//y = pow(rand(x),5.);"></div>
|
|||
|
|
|||
|
Некоторое время назад [Pixelero](https://pixelero.wordpress.com) опубликовал [интересную статью о случайном распределении](https://pixelero.wordpress.com/2008/04/24/various-functions-and-various-distributions-with-mathrandom/). Я добавил несколько функций из неё в график выше, чтобы вы могли поиграться с ними и посмотреть как меняется распределение значений. Раскомментируйте функции и посмотрите что произойдёт.
|
|||
|
|
|||
|
Читая [статью Pixelero](https://pixelero.wordpress.com/2008/04/24/various-functions-and-various-distributions-with-mathrandom/), важно помнить, что функция ```rand()``` является детерминированной, или псевдослучайной. Это означает, что, к примеру, ```rand(1.)``` всегда возвращает одно и то же значение. [Pixelero](https://pixelero.wordpress.com/2008/04/24/various-functions-and-various-distributions-with-mathrandom/) упоминает недетерминированную функцию ```Math.random()``` из ActionScript, которая каждый раз возвращает разные значения.
|
|||
|
|
|||
|
## Двумерная случайность
|
|||
|
|
|||
|
Теперь у нас есть лучшее понимание случайности, и мы можем применить её в двумерном пространстве, к осям ```x``` и ```y``` одновременно. Для этого нам нужен способ преобразования двумерного вектора в одномерное значение с плавающей точкой. Можно придумать много способов сделать это, например использовать скалярное произведение ([```dot()```](../glossary/?search=dot)). В коде ниже функция от скалярного произведения возвращает единственное число в диапазоне от ```0.0``` до ```1.0``` в зависимости от взаимного расположения векторов.
|
|||
|
|
|||
|
<div class="codeAndCanvas" data="2d-random.frag"></div>
|
|||
|
|
|||
|
Обратите внимания на строки с 13 по 15, где ```vec2 st``` сравнивается с другим двумерным вектором ```vec2(12.9898,78.233)```.
|
|||
|
|
|||
|
* Попробуйте изменить значения в строках 14 и 15. Понаблюдайте за изменениями изображения я и подумайте, какую информацию из этого можно извлечь.
|
|||
|
|
|||
|
* Для лучшего понимания свяжите функцию взятия случайных значений с событиями мыши (```u_mouse```) и временем (```u_time```).
|
|||
|
|
|||
|
## Использование хаоса
|
|||
|
|
|||
|
Случайные значения в двумерном изображении выглядят как шум ненастроенного телевизора, не правда ли? Это слишком жёсткий и сырой материал для создания изображений. Давайте сделаем его более полезным.
|
|||
|
|
|||
|
В качестве первого шага применим к случайному шуму сетку. Используя функцию [```floor()```](../glossary/?search=floor), можно сгенерировать таблицу с целочисленным количеством клеток. Посмотрите на следующий код, особенно на строки 22 и 23.
|
|||
|
|
|||
|
<div class="codeAndCanvas" data="2d-random-mosaic.frag"></div>
|
|||
|
|
|||
|
После увеличения пространства в 10 раз (строка 21), мы отделяем целые части координат от дробных. Эта операция нам уже знакома по разбиению пространства на клетки, в каждой из которых координаты изменяются от ```0.0``` до ```1.0```. Извлекая целую часть координаты мы получаем общее число для всех пикселей одной клетки. Далее мы можем использовать это целое число чтобы сгенерировать случайное число для всей клетки. Так как случайная функция детерминирована, это случайное число получится одинаковым для всех пикселей клетки.
|
|||
|
|
|||
|
Раскомментируйте строку 29, где мы используем сохранённую дробную часть координат пикселя в качестве нормированных координат внутри клетки.
|
|||
|
|
|||
|
Комбинация целой и дробной части координат позволяет смешивать порядок и изменчивость.
|
|||
|
|
|||
|
Посмотрите на GLSL-версию известного генератора лабиринтов ```10 PRINT CHR$(205.5+RND(1)); : GOTO 10```.
|
|||
|
|
|||
|
<div class="codeAndCanvas" data="2d-random-truchet.frag"></div>
|
|||
|
|
|||
|
В нём используется случайное значение клетки для рисования линии в том или ином направлении с помощью функции ```truchetPattern()``` из предыдущей главы (строки с 41 по 47).
|
|||
|
|
|||
|
Раскомментируя строки с 50 по 53, можно получить ещё один интересный узор, а убрав комментарии со строк 35 и 36, вы увидите анимацию.
|
|||
|
|
|||
|
## Мастер Случайность
|
|||
|
|
|||
|
Японский электронный музыкант и художник [Рёдзи Икеда](http://www.ryojiikeda.com/) преуспел в использовании случайности. Сложно противостоять очарованию и гипнотизму его работ. Случайность особым образом вплетена в его работы: там она не создаёт раздражающий хаос, а отражает сложность нашей технологической культуры.
|
|||
|
|
|||
|
<iframe src="https://player.vimeo.com/video/76813693?title=0&byline=0&portrait=0" width="800" height="450" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
|
|||
|
|
|||
|
Посмотрите на работу [Икеды](http://www.ryojiikeda.com/) и попробуйте выполнить следующее:
|
|||
|
|
|||
|
* СДелайте горизонтальное движение клеток со случайными значениями в противоположных направлениях. Показывайте только наиболее светлые клетки. Изменяйте скорость движения клеток со временем.
|
|||
|
|
|||
|
<a href="../edit.php#10/ikeda-00.frag"><canvas id="custom" class="canvas" data-fragment-url="ikeda-00.frag" width="520px" height="200px"></canvas></a>
|
|||
|
|
|||
|
* Точно так же сделайте несколько строк, только каждую с разной скоростью и направлением. Сделайте так, чтобы множество показываемых клеток зависело от положения мыши.
|
|||
|
|
|||
|
<a href="../edit.php#10/ikeda-03.frag"><canvas id="custom" class="canvas" data-fragment-url="ikeda-03.frag" width="520px" height="200px"></canvas></a>
|
|||
|
|
|||
|
* Create other interesting effects.
|
|||
|
|
|||
|
<a href="../edit.php#10/ikeda-04.frag"><canvas id="custom" class="canvas" data-fragment-url="ikeda-04.frag" width="520px" height="200px"></canvas></a>
|
|||
|
|
|||
|
Сделать беспорядок эстетически привлекательным непросто, особенно если вы хотите делать симуляции, которые выглядят естественно. Он слишком хаотичен, и очень немногие из реальных вещей выглядят действительно случайно. Такие хаотичные вещи, как капли дождя или график биржевых котировок, не выглядят похожими на случайный рисунок, который мы делали вначале главы. К чём причина? Ну, случайные значения никак не коррелируют друг с другом, в то время как реальные вещи обычно "помнят"" о своих предыдущих состояниях.
|
|||
|
|
|||
|
В следующей главе мы изучим шум. Это способ создания хаоса с помощью компьютера, который выглядит плавно и естественно.
|