Szumy – wstęp i historia

20.10.2024
Szumy – wstęp i historia TEORIA

Prerekwizyty:

W tym artykule przedstawię Ci czym są szumy i dlaczego są tak ważne w świecie proceduralnie generowanych treści – zarówno od strony algorytmicznej jak i graficznej.

W grach wideo często korzystamy z liczb losowych, co najczęściej możemy zauważyć w grach typu RPG takich jak Baldur’s Gate czy Darkest Dungeon, w których to o sukcesie nie decyduje refleks gracza, a cechy i umiejętności bohaterów. Przykładowo podczas walki każdy atak postaci ma określoną szansę na trafienie przeciwnika, uwzględniając przy tym szereg warunków takich jak umiejętność posługiwania się daną bronią, pancerz przeciwnika itp. „Pod spodem” sprowadza się to do wylosowania liczby z zakresu od 0 do 100 i sprawdzenie czy wynik mieści się w przedziale trafienia – jeśli mamy 95% szans na sukces to wylosowana liczba musi być mniejsza niż 95 i tak dalej. Na tej samej zasadzie liczby determinują czy uda nam się przekonać strażnika do wpuszczenia nas do miasta, uszczuplić sakiewkę nieuważnego kupca czy też znaleźć rzadki przedmiot w skrzyni. Taki system istnieje już od lat w klasycznych, papierowych grach RPG gdzie musimy rzucić kostką, aby zweryfikować sukces lub porażkę naszych działań. Jednak model zupełnie losowych liczb, nawet z uwzględnieniem określonych przedziałów, nie zawsze się sprawdza. Wyobraź sobie, że chcemy stworzyć dwuwymiarowy teren a’la Terraria, z dolinami i wzgórzami. 

W programowaniu najłatwiej jest reprezentować rzeczywistość liczbami, a więc potrzebowalibyśmy takich, które określą wysokość terenu w danym punkcie na mapie. Ustalmy, że losujemy liczby od -1 do 1, gdzie -1 to dno morza, 0 to równiny, a 1 to szczyt góry. Tak mogłoby wyglądać pierwsze 10 wylosowanych liczb:

0.26   0.70   -0.46   -0.95   0.81   -0.08   -0.41   -0.59   0.12   -0.50

Zwróć uwagę, że poza samymi ramami wygenerowanych liczb, są one dość chaotycznie porozrzucane. Liczba -0.95 sugerowałaby głębiny oceanu, zaraz po niej mamy 0.81 czyli bardzo wysoką górę, a potem znowu -0.08 czyli stan poniżej poziomu morza. Poza niektórymi formacjami takimi jak klify, w naturalnym środowisku morze stawałoby się stopniowo coraz bardziej płytkie, następnie wystąpiłyby plaże, równiny, wzgórza, a dopiero potem góry. Po naniesieniu tych wysokości na wykres można sobie zwizualizować jaki teren otrzymalibyśmy generując go w zupełnie losowy sposób:

Przyznasz pewnie, że nie wygląda to tak jak mapa w grze, a co najwyżej jak nasz puls, gdy dowiemy się, że sąsiad kupił sobie lepszy samochód. Wygląda nieskładnie, losowo i przypomina wykres szumu akustycznego, czyli takiego dźwięku jaki wytwarza stary, niezaprogramowany telewizor lub radio.


Szum nie kojarzy nam się z algorytmiką. Myśląc o szumie pewnie przychodzi Ci do głowy dźwięk deszczu, suszarki lub właśnie takiego telewizora. Może nam również szumieć w głowie od natłoku sprzecznych opinii w telewizji czyli szumu informacyjnego. Słownikowych definicji szumu również jest kilka; “zamieszanie wokół kogoś lub czegoś” lub “głuchy, jednostajny dźwięk zakłócający odbiór audycji radiowych, rozmowę telefoniczną” to jedne z nich. Niezależnie od definicji lub rodzaju szumu, będzie się on kojarzyć z czymś losowym, chaotycznym, rozpraszającym, utrudniającym znalezienie konkretnej informacji. Dokładnie tak jak z wylosowanymi przez nas wcześniej liczbami, które “zakłócają” nasz świat wprowadzając skrajnie różne wysokości zbyt blisko siebie uniemożliwiając tym samym stworzenie naturalnej, czytelnej mapy.

I tu pewnie mógłbym powiedzieć “to tyle na dziś, szumy nie są używane w grach, a nazwa mojego bloga jest bez sensu, dziękuję za uwagę” gdyby nie Ken Perlin, który wynalazł swoją własną, zdecydowanie bardziej użyteczną w tej branży wersję szumu, za co jestem mu dozgonnie wdzięczny.

Ken Perlin nie był zadowolony z jakości grafiki generowanej komputerowo podczas swojej pracy nad filmem Tron w 1982 (to ten ze świecącymi motorami). Rok później, po zakończeniu produkcji, stworzył nowatorski algorytm znany dzisiaj jako Szum Perlina, dzięki któremu był w stanie generować naturalnie wyglądające tekstury, które w tamtych czasach nie wyglądały sztucznie. Za swoje osiągnięcie później został nagrodzony Oscarem.


Algorytm Perlina modyfikuje sposób działania zwykłego szumu, wprowadzając równowagę pomiędzy umiarkowaną losowością, a kompletnym chaosem. Na podstawie zaledwie kilku parametrów potrafi wygenerować liczby, które również są losowe, jednak będą podobne do swoich sąsiadów – innymi słowy duża liczba nie będzie bezpośrednio sąsiadować z małą, a stopniowo maleć. Przypomnijmy jak wyglądały liczby kompletnie losowe:

0.26   0.70   -0.46   -0.95   0.81   -0.08   -0.41   -0.59   0.12   -0.50

Ciąg liczb wygenerowany Szumem Perlina jest zdecydowanie mniej chaotyczny. Jedynka nie znajdzie się zaraz obok liczby ujemnej lub nawet zera, a będzie sąsiadować z liczbami takimi jak 0,9, które to z kolei będą podobnie, stopniowo maleć lub rosnąć. Przykładowo:

-0.01   0.13   0.26   0.43   0.51   0.38   0.25   0.12   0.01   -0.11

Jeśli weźmiemy dowolną liczbę takiego ciągu to jej prawy i lewy sąsiad nie będzie się drastycznie od niej różnił – weźmy choćby liczbę 0.26, która nie różni się znacząco ani od 0.13 ani 0.43. Różnice mogą być o wiele mniejsze w zależności od parametrów algorytmu. Gdybyśmy tak wygenerowane liczby nanieśli na wykres, mógłby wyglądać mniej-więcej tak:

Na 1 rzut oka widać, że wykres jest bardziej zrównoważony. Kolejne liczby są losowe, ale nie różnią się znacząco od swoich bezpośrednich sąsiadów. Teraz spróbuj zapomnieć o matematycznej reprezentacji i zwróć uwagę na sam kształt wykresu. Przypomina Ci to coś? Ta, wygenerowane liczby zdecydowanie bardziej pasują do określania wysokości terenu w danym punkcie, ponieważ nie są skrajnie różne od siebie, przez co wygląda on bardziej naturalnie (właśnie o to chodziło Panu Perlinowi). Oprócz ukształtowania terenu, powyższy wykres może nasuwać skojarzenia z wykresem cen akcji w grze ekonomicznej lub zmiany temperatury w czasie w grze o tematyce survivalowej. Przykłady można mnożyć w nieskończoność, a to jedynie wierzchołek góry lodowej.

Wróćmy jednak do samego algorytmu. Do tej pory skupiłem się na szumie Perlina jako jednowymiarowym ciągu liczb, a gdyby zrobić to samo, ale w przestrzeni dwuwymiarowej?

Na osi jednowymiarowej każda liczba miała dwóch sąsiadów – po lewej i po prawej stronie. Teraz każda liczba ma aż 9 sąsiadów, naokoło siebie, jednak zasada działania jest dokładnie taka sama – sąsiedzi nie różnią się wiele od siebie nawzajem. Jeśli “pokolorujemy” każdą liczbę w taki sposób że -1 to czerń, 1 to biel a liczby pomiędzy będą skalą szarości to otrzymamy płynne przejścia pomiędzy tymi kolorami:

Jeśli wygenerujemy Szumem Perlina dużo więcej liczb niż w powyższym kwadracie 5×5 i analogicznie pokolorujemy je na czarno-białą skalę oraz “oddalimy kamerę” to dostaniemy wynik podobny do obrazka poniżej:

Wygląda to zdecydowanie bardziej płynnie niż całkowicie losowe białe i czarne piksele w zepsutym telewizorze, ale co tak naprawdę otrzymaliśmy? Czy ten wzór coś Ci przypomina? A może wystarczy, że go troszkę przemaluję zamieniając czerń na kolor niebieski, szarości na zieleń, a najbielsze punkty potraktuję jako góry i pozostawię na biało i szaro?

Tak właśnie przez zwykłe “pomalowanie” obrazka wykorzystałem Szum Perlina do stworzenia mapy. To esencja tego w jaki sposób twórcy gier i filmów wykorzystują algorytmy proceduralnego generowania. Sam szum niczego specjalnego nie tworzy. Algorytm dostarcza zbiór losowych liczb z łagodnym “przejściem”, a to od nas zależy jak to wykorzystamy. Powyższy szum równie dobrze można by przerobić na podziemie jeśli liczby małe (kolor czarny) potraktujemy jako jaskinie, a duże (kolor biały) – jako ściany. Gdyby trochę bardziej pokombinować, moglibyśmy dorobić różne strefy klimatyczne w ten sposób, aby na północy dominowały lodowe krainy, a na południu – pustynne.

W identyczny sposób jest to używane w grze Rimworld – zwróć uwagę na rozmieszczenie formacji skalnych:

Terraria również korzysta z podobnych rozwiązań do wyznaczania nie tylko powierzchni jaskiń, ale do generowania złóż metali pod ziemią:

Dokładnie tak samo zastosujemy parametry szumu w grafice 3D, traktując wartość szumu w danym punkcie jako wysokość terenu. Zwróć uwagę na poniższą „siatkę”:

Choć w tej postaci nie wygląda nazbyt imponująco, po naniesieniu na nią rozmaitych tekstur i obiektów zacznie wyglądać bardzo naturalnie dzięki ukształtowaniu terenu nadanemu przez wartości szumu. Zresztą nie trzeba sobie tego wyobrażać – zobacz jak to ślicznie wygląda w Rust czy Rimworld:

To zaledwie kilka przykładów, ale jakby się przyjrzeć – szumy można by znaleźć w naprawdę wielu miejscach w grach, również w tych bez proceduralnie generowanych światów. Nawet w animacjach możemy dostrzec podobne wzory – przykładowo w scenie z Elden Ring’a gdzie postać “pali” swoje szaty ujawniając swoje prawdziwe oblicze, lub w Legend of Zelda: Breath of the Wild gdzie na końcu każdego wyzwania posąg w efektowny sposób znika:

Elden Ring
Legend of Zelda: Breath of the Wild

Zwróć uwagę na czerwone lub zielone obwódki – nie przypominają Ci trochę szumu lub omówionych wcześniej wysp? Podobieństwo jest nieprzypadkowe, ponieważ tych samych technik co do generowania światów i obiektów także ochoczo używa się w przeróżnych efektach wizualnych, a zasada działania pozostaje ta sama – mała liczba to brak obiektu, duża liczba to obiekt, a liczby pomiędzy to czerwona / zielona obwódka symulująca “spalanie” lub zanikanie. 

“Dobra Kuba, ale jak to jest, że w tych grach mapa przy każdej rozgrywce jest inna” – zapytasz. Algorytm oczekuje od nas tzw. “seeda”. Zarówno to zjawisko jak i inne parametry szumu opiszę w osobnych artykułach, ale w skrócie seed to po prostu losowa liczba, która jest unikalną wizytówką szumu – tak jak ludzie mają numer pesel. Jeśli podamy inną liczbę do algorytmu, dostaniemy inny szum, a jeśli podamy dwa razy tą samą – dwukrotnie otrzymamy ten sam wynik. Stąd nazwa “seed” czyli ziarno (prawdopodobnie pomysłodawcy chodziło o analogię do natury, gdzie z dwóch identycznych ziaren wyrośnie takie samo drzewko). Jeśli każdy gracz będzie miał inny “seed”, a my napiszemy nasz kod w grze w taki sposób, aby z szumu zrobił morza i wyspy, lub skały i jaskinie, to każdy będzie miał swój własny, unikalny świat. Zobacz jak mogą różnić się szumy w zależności od “seeda”:

Podobne, ale jednak trochę inne. Zupełnie jak mapy w Rust, Rimworld czy Minecraft c’nie? 

Celowo jednak nie nazwałem tego artykułu “Esej o Szumie Perlina”. Co prawda ten był pierwszy i zawdzięczamy mu stworzenie fundamentów współczesnych metod proceduralnego generowania, ale od czasów pierwszego “Trona” powstało wiele innych technik rozwijających ideę Pana Perlina. Same szumy doczekały się wielu modyfikacji stworzonych przez zarówno samego twórcę oryginału jak i innych pasjonatów algorytmiki, jednak zasada zawsze pozostała taka sama – generowany jest zbiór liczb wedle pewnych zasad, który możemy zinterpretować w wybrany przez nas sposób. Oto przykład innych szumów – a jako zadania domowe zastanówcie się co Wam przypominają:

Na koniec warto zaznaczyć, że w większości przypadków dostępne programy do tworzenia gier (Godot, Unreal, Unity itp.) lub grafiki 3D (Blender, 3DsMax) oferują gotowe narzędzia do generowania szumów, więc nie ma potrzeby pisania całego algorytmu od nowa za każdym razem, gdy będziemy chcieli go użyć. Jednak znajomość zarówno jego koncepcji, parametrów jak i samego kodu zdecydowanie pomoże nam umiejętnie wykorzystywać go do wybranych przez nas celów. Dlatego też w kolejnych artykułach przyjrzymy się min. jak generować szum i co oznaczają jego parametry, czym jest min. Simplex / Voronoi / Billow / Rigged Noise, a także postaramy się zrozumieć algorytm szumu i napisać swoje własne programy do generowania światów.

To ja, Kuba

To ja, Kuba

Chcesz być na bieżąco z algorytmami i śmieszkami?

Zapraszam na moje social media!

Ostatnie wpisy

Szum Perlina

W poprzednich artykułach wspominałem czym są szumy i jak są wykorzystywane do tworzenia proceduralnych światów, a dzisiaj przyjrzymy się dokładniej konkretnemu algorytmowi z “rodziny szumów”, a mianowicie - “Szumie Perlina” (Perlin Noise). Tak więc bierz meliskę, włącz sobie swój ulubiony...

20.10.2025
Czytaj więcej