The Book of Shaders by Patricio Gonzalez Vivo & Jen Lowe

Bahasa Indonesia - Tiếng Việt - 日本語 - 中文版 - 한국어 - Español - Portugues - Français - Italiano - Deutsch - Русский - Polski - English


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

Не дивно, що після стількох повторень наших карате-рухів і впорядкованості, автор змушений внести трохи хаосу.

Випадковість

Ryoji Ikeda - тестовий патерн (2008)

Випадковість є максимальним проявом ентропії. Як ми можемо створити випадковість у, здавалося б, передбачуваному та суворому програмному середовищі?

Почнемо з аналізу наступної функції:

Значення sin() коливаються між -1.0 до 1.0. Вище ми витягуємо дробову частину цієї синусоїди, "обрізаючи" та підіймаючи діапазон її негативних значень до позитивних в межах від 0.0 до 1.0. Цей ефект можна використати, щоб отримати деякі псевдовипадкові значення, "розбивши" синусоїду на менші частини. Як? За допомогою помноження результату sin(x) на більші числа. Поверніться до прикладу і почніть додавати нулі до цілої частини множника.

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

Управління хаосом

Використання випадковості може бути важкою справою. Інколи вона буває занадто хаотичною, а часом недостатньо випадковою. Подивіться на наступний графік. В ньому ми використовуємо функцію rand(), яка реалізована так само як ми описали вище.

Придивившись ближче, ви можете побачити гребні у sin()-хвилі по x-вісі біля значень -1.5707 та 1.5707. Б'юся об заклад, тепер ви розумієте чому — саме там відбувається максимум і мінімум синусоїди.

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

Свого часу Pixelero опублікував цікаву статтю про випадковий розподіл. Я додав декілька його прикладів до попереднього графіка, щоб ви могли пограти з ними та побачити, як можна змінити розподіл значень. Розкоментуйте рядки та подивіться, що станеться.

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

Двомірна випадковість

Тепер, коли ми краще розуміємо випадковість, настав час застосувати її у двомірному просторі, до осей x та y. Для цього нам потрібен спосіб перетворити двовимірний вектор в одновимірне значення з рухомою крапкою. Існують різні способи зробити це, але функція dot() особливо корисна в цьому випадку. Вона повертає єдине float-значення між 0.0 і 1.0 залежно від розташування двох векторів.

Подивіться на рядки з 13 по 15 і зверніть увагу на те, як ми порівнюємо vec2 st з іншим двовимірним вектором (vec2(12.9898, 78.233)).

Використання хаосу

Випадкові значення у двовимірному зображенні дуже схожі на телевізійний шум, чи не так? Це жорсткий та занадто сирий матеріал для створення зображень. Навчімось же ним користуватися.

Першим кроком застосуємо до нього сітку. За допомогою функції floor() ми згенеруємо таблицю з цілочисельною кількістю клітинок. Подивіться на наступний код, особливо на рядки 22 і 23:

Після збільшення простору у 10 разів (рядок 21), ми відокремлюємо цілі числа координат від дробової частини (рядок 22). Ми знайомі з цією операцією, тому що вже використовували її для поділу простору на менші комірки, що йдуть від 0.0 до 1.0. Отримавши ціле значення координати, ми виокремлюємо загальне значення кількості пікселів, необхідних для побудови одної комірки. Далі ми можемо використовувати це ціле число, щоб отримати випадкове значення для цієї області. Оскільки наша випадкова функція є детермінованою, то випадкове значення, що повертається, буде постійним для всіх пікселів у цій клітинці.

Розкомментуйте рядок 29, щоб побачити, що ми зберігаємо дробову частину координати (рядок 23), тому ми все ще можемо використовувати її як нормовану систему координат для кожної окремої клітинки.

Поєднання цілої та дробової частин координати дозволить змішувати варіацію та порядок.

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

Тут я використовую випадкові значення комірок для малювання лінії в одному чи іншому напрямку за допомогою функції truchetPattern() із попереднього розділу (рядки 41-47).

Розкоментувавши блок рядків з 50 по 53, ви можете отримати інший цікавий патерн, або анімувати його, розкоментувавши рядки 35 і 36.

Майстер випадковості

Ryoji Ikeda — японський електронний композитор і візуальний художник, який опанував використання випадковості. Важко залишитись байдужим та не стати загіпнозованим його роботами. При використанні випадковості у своїх аудіо- та візуальних середовищах він не перетинає межу дратівливого хаосу та відзеркалює складність нашої технологічної культури.

Перегляньте роботу Ikeda і спробуйте виконати такі вправи:

Використовування випадковості для отримання естетичних результатів може бути проблематичним, особливо якщо ви хочете зробити симуляції, що виглядатимуть природно. Випадковість занадто хаотична й дуже мало речей виглядають рандомно у реальному житті. Якщо поглянути на патерн дощу або біржову діаграму, які є досить випадковими, то вони зовсім не схожі на ту модель випадковості, яку ми створили на початку цього розділу. В чому причина? Ну що ж, просто ці випадкові значення не мають ніякої кореляції між собою, а більшість природних шаблонів мають певну "пам'ять" про свій попередній стан.

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