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


Design generatywny

Nie jest zaskoczeniem, że po tylu zagadnieniach ładu i porządku autor zmuszony jest wprowadzić trochę chaosu.

Losowość

Ryoji Ikeda - test pattern (2008)

Losowość jest maksymalnym wyrazem entropii. Jak możemy wygenerować losowość wewnątrz pozornie przewidywalnego i sztywnego środowiska kodu?

Zacznijmy od analizy następującej funkcji:

Powyżej wyodrębniamy zawartość ułamkową sinusoidy. Wartości sin(), które oscylują pomiędzy -1.0 a 1.0 zostały posiekane, i sprowadzone do zakresu pomiędzy 0.0 a 1.0. Możemy wykorzystać ten efekt do uzyskania pseudolosowych wartości. W jaki sposób? Mnożąc wypadkową sin(x) przez większe liczby. Śmiało, zmodyfikuj powyższą funkcję, dodając zera do 1.0.

Do czasu, gdy dojdziesz do 100000.0 (i równanie będzie wyglądało tak: y = fract(sin(x)*100000.0) ) nie jesteś już w stanie dostrzec sinusoidę. Ziarnistość części ułamkowej zepsuła falę sinusoidy w pseudolosowy chaos.

Kontrolowanie chaosu

Używanie losowości może być trudne - czasami jest ona zbyt chaotyczna, a czasami niewystarczająco losowa. Przyjrzyj się poniższemu wykresowi. Aby go stworzyć, używamy funkcji rand(), która jest zaimplementowana dokładnie tak, jak opisaliśmy powyżej.

Przyglądając się bliżej, możesz dostrzec osobiliwości przy -1.5707 i 1.5707. Założę się, że teraz rozumiesz dlaczego - to właśnie tam występuje maksimum i minimum fali sinusoidalnej.

Jeśli przyjrzysz się bliżej rozkładowi losowemu, zauważysz, że istnieje pewne skupienie wokół środka w porównaniu do brzegów.

Jakiś czas temu Pixelero opublikował ciekawy artykuł o rozkładzie losowym. Dodałem kilka zakomentowanych funkcji, których używa, abyś mógł zobaczyć, jak można ten rozkład zmienić. Odkomentuj te funkcje i zobacz, co się stanie.

Czytając artykuł Pixelero, ważne jest, aby pamiętać, że nasza funkcja rand() jest deterministyczna, pseudolosowa. Co oznacza, że na przykład rand(1.) zawsze zwróci tę samą wartość. Pixelero odwołuje się do funkcji ActionScript Math.random(), która jest niedeterministyczna - każde jej wywołanie zwróci inną wartość.

Losowość 2D

Teraz, gdy mamy już lepsze zrozumienie losowości, czas zastosować ją w dwóch wymiarach, zarówno na osi x jak i y. W tym celu potrzebujemy sposobu na przekształcenie dwuwymiarowego wektora w jednowymiarową wartość zmiennoprzecinkową. Można to zrobić na różne sposoby, ale szczególnie pomocna w tym przypadku jest funkcja dot(). Zwraca ona pojedynczą wartość zmiennoprzecinkową pomiędzy 0.0 a 1.0 w zależności od wzajemnej orientacji dwóch wektorów.

Przyjrzyj się liniom od 13 do 15 i zauważ, jak porównujemy vec2 st z innym dwuwymiarowym wektorem ( vec2(12,9898,78,233)).

Wykorzystanie chaosu

Losowość w dwóch wymiarach wygląda bardzo podobnie do szumu telewizyjnego, prawda? To trudne do wykorzystania narzędzie do komponowania obrazów. Nauczmy się, jak zrobić z niego użytek.

Naszym pierwszym krokiem jest stworzenie tablicy kafelków; używając funkcji floor() wygenerujemy tablicę, w której każdemu kafelkowi przyporządkowany jest unikalny wektor liczb całkowitych. Przyjrzyj się poniższemu kodowi, szczególnie liniom 22 i 23.

Po przeskalowaniu przestrzeni przez 10 (w linii 21) oddzielamy część całkowitą współrzędnych od części ułamkowej. Operacja uzyskiwania części ułamkowej jest nam dobrze znana, ponieważ używaliśmy jej do dzielenia przestrzeni na mniejsze kafelki o wartościach od 0.0 do 1.0. Uzyskując część całkowitą współrzędnej wyodrębniamy wspólną wartość dla całego kafelka. Następnie możemy użyć tej wspólnej liczby całkowitej, aby uzyskać losową wartość dla tego kafelka. Ponieważ nasza funkcja losowa jest deterministyczna, zwrócona wartość losowa będzie stała dla wszystkich pikseli w tym kafelku.

Odkomentuj linię 29, aby zobaczyć, że zachowujemy część ułamkową współrzędnej, więc możemy nadal używać jej jako układu współrzędnych do rysowania rzeczy wewnątrz każdego kafelka.

Połączenie tych dwóch wartości - części całkowitej i części ułamkowej współrzędnej - pozwoli ci wymieszać zmienność i porządek.

Spójrz na poniższy GLSL'owy port słynnego generatora labiryntów 10 PRINT CHR$(205,5+RND(1)); : GOTO 10.

Tutaj wykorzystuję losowe wartości kafelków do rysowania linii w jednym lub drugim kierunku, używając funkcji truchetPattern() z poprzedniego rozdziału (linie 41 do 47).

Możesz uzyskać inny ciekawy wzór, odkomentowując blok linii między 50 a 53, natomiast odkomentowując linie 35 i 36 dodasz animację.

Ujarzmij losowość

Ryoji Ikeda, japoński kompozytor elektroniczny i artysta wizualny, ujarzmił losowość - trudno nie być poruszonym i zahipnotyzowanym przez jego prace. Jego użycie losowości w mediach audio-wizualnych to nie irytujący chaos, ale lustro złożoności naszej technologicznej kultury.

Zapoznaj się z pracami Ikedy i spróbuj wykonać następujące ćwiczenia:

Używanie losowości w estetyczny sposób może być problematyczne, zwłaszcza jeśli chcesz zrobić naturalnie wyglądające symulacje. Losowość jest po prostu zbyt chaotyczna i bardzo niewiele rzeczy wygląda random() w prawdziwym życiu. Jeśli spojrzysz na wzór deszczu lub wykres giełdowy, które są dość losowe, nie przypominają one w niczym losowego wzoru, który stworzyliśmy na początku tego rozdziału. Powód? Cóż, wartości losowe nie mają żadnej korelacji między sobą, podczas gdy większość naturalnych wzorów ma jakąś pamięć o poprzednim stanie.

W następnym rozdziale poznamy szum (ang. "noise"), płynny i naturalnie wyglądający sposób tworzenia chaosu obliczeniowego.