Ogromne światy generowane proceduralnie

76

Jestem pewien, że wszyscy znacie takie gry, jak Dwarf Fortress - ogromna, generowana proceduralnie dzicz i ziemia. Coś takiego, zaczerpnięte z tego bardzo przydatnego artykułu.

Zastanawiałem się jednak, jak to zastosować na znacznie większą skalę; przychodzi mi na myśl skala Minecrafta (czy to nie jest około 8 razy większa od powierzchni Ziemi?). Pseudo-nieskończoność, myślę, że najlepszym terminem byłoby.

:RE

Artykuł mówi o fraktalnym hałasie perlina. Nie jestem ekspertem od tego, ale mam ogólny pomysł (to jakiś rodzaj generowanego losowo szumu, który jest częściowo spójny, więc nie tylko losowe wartości pikseli).

Mógłbym po prostu zdefiniować regiony X na X, dodać elementy ładujące region i mieć jeden bit hałasu generujący region. Ale spowodowałoby to po prostu ogromne ilości wysp.

Z drugiej strony, nie sądzę, że naprawdę mogę wygenerować supermasywny hałas perlina. I myślę, że to tylko jedna wielka wyspa.

Jestem pewien, że hałas Perlina lub jakiś hałas byłby w jakiś sposób odpowiedzią. Mam na myśli, że mapa wygląda naprawdę ładnie. I możesz wymienić ascii na płytki i uzyskać coś bardzo ładnie wyglądającego.

Kaczka komunistyczna
źródło
9
„spowodowałoby to po prostu ogromne ilości wysp” - Lub generuje ziemię z jeziorami, jeśli po prostu zamienisz ziemię / wodę.
3
Mimo to dostaniesz dużą liczbę jezior, w dość standardowym wzorze.
Kaczka komunistyczna
3
@Kylotan: Mincraft ma nieskończony rozmiar (no nie bardzo, ale jest naprawdę duży ... całkowita objętość = długa.MaxValue x 128 x long.MaxValue). Dlatego nie generuje całego świata w jednym ujęciu, ani nie przechowuje całej mapy w pamięci. Generuje asynchronicznie regiony bloków 16 x 128 x 16, jeśli nie były wcześniej odwiedzane, w przeciwnym razie ładuje je z dysku.
zfedoran,
2
@The Communist Duck: Tak, to prawda, taka gra jak Minecraft może uciec z wykorzystaniem około 2 do 4 bajtów danych na blok, ale tylko bajt musi zostać zapisany, gdy nie jest już widoczny (jeden bajt opisuje rodzaj bloku , pozostałe bajty opisują oświetlenie i inne dane, które można ponownie przeliczyć). Tutaj jest to interesujące, możesz użyć RLE, aby drastycznie zmniejszyć przechowywany rozmiar do zaledwie kilku bajtów, ponieważ bloki są dość spójne, jak wspomniałeś.
zfedoran,
4
„Naprawdę duży” to nie to samo co nieskończoność i nie można używać obu terminów zamiennie. Jeśli powiększysz mapę w momencie jej odkrycia, będzie to skończony rozmiar, który rośnie na żądanie - zupełnie inna propozycja niż nieskończoność. Każdy kawałek wzrostu można wygenerować w razie potrzeby. Dane terenu w Minecraft są bardzo podatne na trywialną kompresję, ponieważ istnieje wysoki stopień spójności między danymi. (np. RLE jak wspomniano.)
Kylotan,

Odpowiedzi:

35

Myślę, że lepiej rozumiem, o co teraz pytasz.

Hałas nie jest przypadkowy - wygląda losowo, ale jest całkowicie oparty na matematycznym wzorze i jest powtarzalny. Wszystkie informacje są zakodowane w formule. Oznacza to, że możesz mieć formułę, która potencjalnie obejmuje nieskończony obszar, i po prostu użyj formuły na współrzędnych potrzebnego obszaru. Kiedy potrzebujesz sąsiedniego obszaru, po prostu ponownie użyj formuły na nowych współrzędnych, a ponieważ formuła daje ciągłe wartości, obszary będą łączyć się płynnie.

Oto uproszczony przykład, w którym do generowania wysokości wykorzystywany jest sinus zamiast szumu perlin i wyobrażenie sobie, że świat jest nieskończony w osi X, ale tylko o 1 jednostkę wysoko w osiach Y i Z.

Formula to: height(x,y) = sin(x/20)

Gra się rozpoczyna, a my generujemy wysokości dla pobliskiego obszaru, tj. (0,0) do (9,0):

[0.0, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.34, 0.39, 0.43]

Mamy wzgórze, wznoszące się w prawo. Powiedzmy, że doszliśmy do końca i musimy teraz wygenerować wartości od (10,0 do 19,0):

[0.48, 0.52, 0.56, 0.61, 0.64, 0.68, 0.72, 0.75, 0.78, 0.81]

Zauważ, że wzgórze stale rośnie i że wartość przy (10,0) ładnie wynika z wartości przy (9,0). Wynika to z faktu, że funkcja sinusoidalna jest ciągła, co w zasadzie oznacza, że ​​jeśli podasz jej 2 sąsiednie liczby, otrzymasz 2 sąsiednie wyniki - dla pewnej definicji sąsiedniej. Więc jeśli użyjesz swoich współrzędnych świata jako parametrów funkcji, która definiuje twój świat, otrzymasz ciągły krajobraz, który będzie do siebie pasował, bez względu na to, ile z niego wygenerujesz, czy niewiele. Po wygenerowaniu nowych części będą one automatycznie przepływały z istniejących części, ponieważ wysokości są już wcześniej ustalone.

Jeśli świat się nie zmieni, nie musisz nawet niczego przechowywać, ponieważ na podstawie wzoru możesz dokładnie obliczyć wysokość w danym punkcie. Oczywiście z czymś takim jak Minecraft świat jest całkowicie odkształcalny, więc po prostu zapisujesz każdy fragment podczas jego tworzenia. Biorąc pod uwagę, że istnieje wysoki stopień spójności między sąsiednimi kawałkami (np. Jeśli 1 blok jest trawą, bardziej prawdopodobne jest, że obok niego też nie będzie trawa), możesz bardzo skutecznie kompresować dane - kodowanie długości przebiegu zadziałałoby no cóż, ale wtedy prawie każdy standardowy algorytm kompresji.

Podczas gdy mówiłem o wysokości jako najbardziej oczywistej wartości, możesz użyć tego samego systemu do wygenerowania dowolnej cechy, którą chcesz. Użyj funkcji matematycznej z ciągłymi właściwościami i gdzie dane wejściowe są twoimi współrzędnymi świata, i które mogą decydować o obecności punktów orientacyjnych, złóż mineralnych, punktów odradzania, co tylko chcesz. (Oczywiście wartości w jednym wzorze mogą mieć wpływ na inny - nie ma sensu umieszczać złoża węgla w powietrzu, więc generujesz mapę wysokości świata, a następnie obliczasz możliwości węgla dla bloków, które są wystarczająco głęboko pod ziemią).

Kylotan
źródło
Zdecydowanie pomogłeś wyjaśnić, dzięki. :) Ale coś w rodzaju funkcji szumu nie byłoby ciągłe. I AFAICS, jeśli jest ciągły, nie otrzymałbym „losowego” świata. A może coś tu brakuje?
Kaczka komunistyczna
Przepraszam za podwójny komentarz, ale uważam, że powyższe jest odrębne od tego. Kiedy powiesz „użyj współrzędnych świata dla hałasu perlin”, czy byłby to ten sam efekt, co generowanie „ogromnego” arkusza hałasu, ale częściowo? Dzisiaj czuję się trochę powolny.
Kaczka komunistyczna
No cóż, generowanie hałasu z pewnością może być ciągłe i zwykle tak jest, ponieważ go wygładzasz. Aby wygładzić ponad granicami, być może trzeba trochę przeczytać za granicą, ale zasada pozostaje taka sama. Jeśli dany hałas wymaga danych pseudolosowych, generujesz je na podstawie znanych ilości - tj. skrót waszych światowych współrzędnych. Dane wyjściowe są następnie przewidywalne.
Kylotan
2
Jeśli chodzi o losowość, każdy świat może mieć własną wartość początkową, która jest wykorzystywana w obliczeniach. na przykład. sin (x + seed) zamiast sin (x), w moim przykładzie powyżej. Każde inne ziarno wygeneruje inny świat. A jeśli chodzi o ogromny arkusz ... Nie jestem pewien, jakie to ma znaczenie. Nie ma znaczenia, ile lub jak mało generujesz lub kiedy to robisz. Początkowy stan świata jest określony przez wzór matematyczny, a ty po prostu używasz tego wzoru, aby odkryć ten stan, kiedy i kiedy go potrzebujesz.
Kylotan
32

Ten samouczek, który napisałem lata temu, może dać ci coś takiego, jak chcesz:

alternatywny tekst

Jeśli wykonasz modyfikację wyspy w ostatnim kroku, zmierza ona w kierunku pojedynczego lądu, który nie dociera do krawędzi mapy.

hojny
źródło
7
Świetne wizualizacje!
zfedoran
3
Pamiętam, jak korzystałem z tego samouczka podczas pracy magisterskiej na temat symulacji zjawisk naturalnych. Użyłem przykładu „wzgórza”, aby stworzyć kopułę nieba nad moim światem 3D. Doskonałe wprowadzenie do koncepcji generowania terenu.
C.McAtackney
1
Szalony, to niesamowite! Nie wiedziałem, że ktoś tak naprawdę z niego korzystał.
hojny
1
O MÓJ BOŻE !!! Użyłem tego również w poprzednim projekcie ... najprostszym sposobie generowania terenu, na jaki się natknąłem !!!
Wojna
15

Aby stworzyć dużą wyspę, nie trzeba jej generować naraz. Budowałbym regiony asynchronicznie podczas ich odwiedzania.

Zamiast używać maski do stworzenia wyspy, jak opisano w artykule, jedną rzeczą, którą możesz zrobić, jest bawić się długością fali oktawowej szumu perlin, aby uzyskać pożądany efekt. Zwykle pierwsza oktawa opisuje ogólny kształt terenu. Wszystkie oktawy po nim dodają po prostu więcej drobnych szczegółów. Dlatego graj z długością fali pierwszej oktawy, aby kontrolować, jak duże będą twoje masy lądowe. Jeśli chcesz, aby ląd znajdował się w centrum, możesz po prostu zmniejszyć mapę wysokości o rosnącą wartość, gdy odsuniesz się od centrum, a następnie znormalizujesz hałas. Wyobraź sobie na przykład połączenie tych dwóch, aby stworzyć swoją wyspę:

pierwsza oktawa Detale

Ten artykuł powinien pomóc: http://freespace.virgin.net/hugo.elias/models/m_perlin.htm

Jeśli chcesz dowiedzieć się o nieskończonych światach 3d i różnych sztuczkach, których możesz użyć, aby zmienić wygląd terenu poprzez zabawę z wejściem i wyjściem hałasu, zapoznaj się z tym artykułem: http://http.developer.nvidia.com /GPUGems3/gpugems3_ch01.html

Może to być trochę trudny do odczytania, jeśli nie znasz programowania grafiki i programowania shaderów.

zfedoran
źródło
Efekt, który chcę osiągnąć, to coś w rodzaju 2D na mapie Minecrafta (nie gra) ... jeśli użyłem mniejszej liczby oktaw, czy nie musiałbym generować ogromnego szumu perlin? Czy mógłbym w jakiś sposób wygenerować bardzo, bardzo małą jego ilość?
Kaczka komunistyczna
Myślę, że nadal możesz być nieco zdezorientowany, jak działa perlin hałas. Możesz wygenerować pojedyncze fragmenty bloków 16x16, wysyłając funkcję przesunięcia współrzędnych xiy dla szumu perlin. Zauważ, jak funkcja PerlinNoise_2D (liczba zmiennoprzecinkowa x, liczba zmiennoprzecinkowa y) przyjmuje współrzędną xiy. Innymi słowy, generuje szum dla niektórych pozycji (x, y). Ponadto generowanie mniejszej liczby oktaw nie jest tym samym, co zmiana długości fali oktaw. Mniej oktaw = = Mniej szczegółów drobnych ziaren. Dłuższa długość fali => więcej powiększenia.
zfedoran
Również tutaj jest artykuł z kodem, który pokazuje, jak wdrożyć zoom / dłuższe długości fal: dreamincode.net/forums/topic/66480-perlin-noise
zfedoran
7

Hałas Perlina i przyjaciele to dobry punkt wyjścia, ale prawdopodobnie chcesz pójść o krok dalej. Większość popularnych generatorów hałasu generuje dość nieciekawe wyniki. Aby teren był realistyczny, warto przyjrzeć się algorytmom emulującym efekty erozji. Jeden z najbardziej zaawansowanych symulatorów świata - Dwarf Fortress - wykonuje symulację erozji jako jeden z etapów budowania świata.

Jedno z całkiem fajnych rozwiązań, które widziałem, zostało opisane w artykule „Zaawansowane osadzanie cząstek” w Gems Programming Game 7. Istnieje wiele innych dostępnych w Internecie, więc jest wiele zasobów, z których można czerpać (np. 1 lub 2 ) .

Dominik D.
źródło