thebookofshaders/10/README-ru.md
2017-09-12 08:54:28 +07:00

12 KiB
Raw Blame History

Генеративный дизайн

Не удивительно, что после стольких повторений и порядка, автор вынужден привнести немного хаоса.

Случайность

Рёдзи Икеда - тестовый шаблон (2008)

Случайность есть сильнейшее проявление энтропии. Но как получить случайность в казалось бы предсказуемом и строгом программном окружении?

Давайте начнём со следующей функции:

Выше мы извлекаем дробную часть синусоиды. Таким образом, значения синуса, плавно изменяющиеся от -1.0 до 1.0, урезается до положительного диапазона от 0.0 до 1.0. Этот эффект можно использовать для получения псевдослучайных значений, "разбивая" синусоиду на меньшие кусочки. Как? Умножением значения синуса на большие числа. Попробуйте добавить нулей в функцию выше.

Когда коэффициент достигнет 100000.0 (то есть когда функция примет вид y = fract(sin(x)*100000.0)), волны синусоиды станут неразличимыми. Дискретность дробной части повредила плавное течение синусоидальной волны, превратив её в псевдослучайный хаос.

Управление хаосом

Использование случайности может стать непростой задачей. Она одновременно бывает слишком хаотичной и не слишком случайной. Посмотрите на следующий график. В нём мы используем функцию rand(), реализованную в точности как показано выше.

Присмотревшись, можно увидеть гребень синусоидальной волны в точках -1.5707 и 1.5707. Легко понять почему: именно в этих точках синус достигает максимума и минимума.

Так же при детальном рассмотрении видно, что значения больше концентрируются в середине, чем на краях полосы.

Некоторое время назад Pixelero опубликовал интересную статью о случайном распределении. Я добавил несколько функций из неё в график выше, чтобы вы могли поиграться с ними и посмотреть как меняется распределение значений. Раскомментируйте функции и посмотрите что произойдёт.

Читая статью Pixelero, важно помнить, что функция rand() является детерминированной, или псевдослучайной. Это означает, что, к примеру, rand(1.) всегда возвращает одно и то же значение. Pixelero упоминает недетерминированную функцию Math.random() из ActionScript, которая каждый раз возвращает разные значения.

Двумерная случайность

Теперь у нас есть лучшее понимание случайности, и мы можем применить её в двумерном пространстве, к осям x и y одновременно. Для этого нам нужен способ преобразования двумерного вектора в одномерное значение с плавающей точкой. Можно придумать много способов сделать это, например использовать скалярное произведение (dot()). В коде ниже функция от скалярного произведения возвращает единственное число в диапазоне от 0.0 до 1.0 в зависимости от взаимного расположения векторов.

Обратите внимания на строки с 13 по 15, где vec2 st сравнивается с другим двумерным вектором vec2(12.9898,78.233).

  • Попробуйте изменить значения в строках 14 и 15. Понаблюдайте за изменениями изображения я и подумайте, какую информацию из этого можно извлечь.

  • Для лучшего понимания свяжите функцию взятия случайных значений с событиями мыши (u_mouse) и временем (u_time).

Использование хаоса

Случайные значения в двумерном изображении выглядят как шум ненастроенного телевизора, не правда ли? Это слишком жёсткий и сырой материал для создания изображений. Давайте сделаем его более полезным.

В качестве первого шага применим к случайному шуму сетку. Используя функцию floor(), можно сгенерировать таблицу с целочисленным количеством клеток. Посмотрите на следующий код, особенно на строки 22 и 23.

После увеличения пространства в 10 раз (строка 21), мы отделяем целые части координат от дробных. Эта операция нам уже знакома по разбиению пространства на клетки, в каждой из которых координаты изменяются от 0.0 до 1.0. Извлекая целую часть координаты мы получаем общее число для всех пикселей одной клетки. Далее мы можем использовать это целое число чтобы сгенерировать случайное число для всей клетки. Так как случайная функция детерминирована, это случайное число получится одинаковым для всех пикселей клетки.

Раскомментируйте строку 29, где мы используем сохранённую дробную часть координат пикселя в качестве нормированных координат внутри клетки.

Комбинация целой и дробной части координат позволяет смешивать порядок и изменчивость.

Посмотрите на GLSL-версию известного генератора лабиринтов 10 PRINT CHR$(205.5+RND(1)); : GOTO 10.

В нём используется случайное значение клетки для рисования линии в том или ином направлении с помощью функции truchetPattern() из предыдущей главы (строки с 41 по 47).

Раскомментируя строки с 50 по 53, можно получить ещё один интересный узор, а убрав комментарии со строк 35 и 36, вы увидите анимацию.

Мастер Случайность

Японский электронный музыкант и художник Рёдзи Икеда преуспел в использовании случайности. Сложно противостоять очарованию и гипнотизму его работ. Случайность особым образом вплетена в его работы: там она не создаёт раздражающий хаос, а отражает сложность нашей технологической культуры.

Посмотрите на работу Икеды и попробуйте выполнить следующее:

  • СДелайте горизонтальное движение клеток со случайными значениями в противоположных направлениях. Показывайте только наиболее светлые клетки. Изменяйте скорость движения клеток со временем.

  • Точно так же сделайте несколько строк, только каждую с разной скоростью и направлением. Сделайте так, чтобы множество показываемых клеток зависело от положения мыши.

  • Create other interesting effects.

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

В следующей главе мы изучим шум. Это способ создания хаоса с помощью компьютера, который выглядит плавно и естественно.