Enormi mondi "selvaggi" generati proceduralmente


76

Sono sicuro che tutti voi conoscete giochi come Dwarf Fortress - terre selvagge e terra generose e procedurali. Qualcosa del genere, tratto da questo articolo molto utile.

Tuttavia, mi chiedevo come avrei potuto applicarlo a una scala molto più ampia; viene in mente la scala di Minecraft (non è forse qualcosa come 8 volte la dimensione della superficie terrestre?). Pseudo-infinito, penso che il termine migliore sarebbe.

: D

L'articolo parla del rumore del perlin frattale. Non ne sono affatto un esperto, ma ho un'idea generale (è una sorta di rumore generato casualmente che è semi-coerente, quindi non solo valori di pixel casuali).

Potrei semplicemente definire le aree di dimensioni X per X, aggiungere elementi di tipo caricamento delle regioni e avere un po 'di rumore che genera una regione. Ma ciò comporterebbe solo enormi quantità di isole.

Dall'altro estremo, non credo di poter davvero generare un foglio supermassiccio di rumore perlin. E sarebbe solo una grande isola, credo.

Sono abbastanza sicuro che il rumore di Perlin, o un po 'di rumore, sarebbe la risposta in qualche modo. Voglio dire, la mappa è davvero carina. E potresti sostituire gli ascii con piastrelle e ottenere qualcosa di molto bello.


9
"porterebbe solo a enormi quantità di isole" - O genera terra con laghi, se si scambia terra / acqua.

3
Anche così, otterresti una grande quantità di laghi, in uno schema abbastanza standard.
Il comunista Duck,

3
@Kylotan: Mincraft ha dimensioni infinite (beh, non proprio, ma è davvero grande ... volume totale = long.MaxValue x 128 x long.MaxValue). Pertanto, non genera l'intero mondo in un colpo solo e non memorizza l'intera mappa in memoria. Genera regioni di blocchi 16x128x16 in modo asincrono se non sono state visitate prima, altrimenti le carica dal disco.
zfedoran,

2
@The Communist Duck: Sì, è vero, un gioco come Minecraft può cavarsela usando circa 2-4 byte di dati per blocco ma solo un byte deve essere salvato dopo che non è più visibile (un byte descrive il tipo di blocco , gli altri byte descrivono l'illuminazione e altri dati che possono essere ricalcolati in seguito). Qui è dove diventa interessante, puoi usare RLE per ridurre drasticamente la dimensione memorizzata fino a pochi byte poiché i blocchi sono in qualche modo coerenti, come hai detto.
zfedoran,

4
"Davvero grande" non è lo stesso di infinito e non è possibile utilizzare i due termini in modo intercambiabile. Se cresci la mappa come e quando viene scoperta, questa è una dimensione finita che cresce su richiesta - una proposta del tutto diversa dall'essere infinita. Ogni bit di crescita può essere generato secondo necessità. I dati del terreno in Minecraft sono molto suscettibili di compressione banale poiché c'è un alto grado di coerenza tra i dati. (es. RLE come menzionato.)
Kylotan,

Risposte:


35

Penso di capire meglio cosa stai chiedendo ora.

Il rumore non è casuale: ha un aspetto casuale ma è completamente basato su una formula matematica ed è ripetibile. Tutte le informazioni sono codificate nella formula. Ciò significa che puoi avere una formula che potenzialmente copre un'area infinita e usare semplicemente la formula sulle coordinate dell'area di cui hai bisogno. Quando hai bisogno di un'area adiacente, devi semplicemente riutilizzare la formula sulle nuove coordinate e poiché la formula fornisce valori continui, le aree si uniranno senza soluzione di continuità.

Ecco un esempio semplificato, usando il rumore sinusoidale invece del perlin per la generazione dell'altezza, e immaginare il mondo è infinito nell'asse X ma solo 1 unità alta negli assi Y e Z.

La formula è: height(x,y) = sin(x/20)

Il gioco inizia e generiamo altezze per l'area vicina, ad es. Da (0,0) a (9,0):

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

Abbiamo una collina, che sale verso destra. Diciamo che camminiamo fino alla fine e dobbiamo generare i valori da (10,0 a 19,0) ora:

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

Notare come la collina continua a salire costantemente e che il valore di (10,0) segue piacevolmente quello di (9,0). Questo perché la funzione seno è continua, il che significa sostanzialmente che se lo inserisci 2 numeri adiacenti, otterrai 2 risultati adiacenti - per una certa definizione di adiacente. Quindi, se usi le coordinate del tuo mondo come parametri della funzione che definisce il tuo mondo, otterrai un paesaggio continuo che si adatta insieme, indipendentemente da quanto o poco ne generi in una volta. Quando si generano nuove parti, queste fluiranno automaticamente dalle parti esistenti, poiché le altezze sono già predeterminate.

Se il mondo non cambierà, non è nemmeno necessario memorizzare nulla, dal momento che puoi calcolare esattamente quale sia l'altezza in un dato punto dalla formula. Ovviamente con qualcosa come Minecraft il mondo è totalmente deformabile, quindi ti basta salvare ogni pezzo mentre lo crei. Dato che esiste un alto grado di coerenza tra blocchi adiacenti (ad es. Se 1 blocco è erba, è più probabile che non anche il blocco accanto ad esso sia erba) è possibile comprimere i dati in modo molto efficiente - la codifica della lunghezza di esecuzione funzionerebbe bene, ma così sarebbe quasi ogni algoritmo di compressione standard.

Mentre ho parlato dell'altezza come il valore più ovvio, puoi usare lo stesso sistema per generare qualsiasi caratteristica tu voglia. Usa una funzione matematica con proprietà continue e in cui gli input sono le tue coordinate mondiali e che può decidere la presenza di punti di riferimento, depositi minerali, punti di spawn, qualunque cosa tu voglia. (Ovviamente i valori di una formula possono influire su un'altra: non ha senso collocare un deposito di carbone a mezz'aria, quindi si genera la mappa dell'altezza mondiale e quindi si calcolano solo le possibilità di carbone per i blocchi abbastanza lontani dal terreno.)


Hai sicuramente contribuito a chiarire le cose, grazie. :) Ma qualcosa come una funzione di rumore non sarebbe continua. E AFAICS, se è continuo non riceverei un mondo "casuale". O mi sto perdendo qualcosa qui?
The Communist Duck,

Ci scusiamo per il doppio commento, ma ritengo che quanto sopra sia separato da questo. Quando dici "usa le coordinate del mondo per il rumore del perlin", questo sarebbe lo stesso tipo di effetto che genera il "grande" foglio di rumore ma in parte? Oggi mi sento un po 'lento sull'assunzione.
The Communist Duck,

Bene, la tua generazione di rumore può certamente essere continua, e di solito lo è, perché lo appianerai. Per smussare i confini potresti dover leggere un po 'oltre il confine, ma il principio rimane lo stesso. Se il rumore in questione necessita di dati pseudo-casuali, allora lo si genera da quantità note, ad es. un hash delle coordinate del tuo mondo. Gli output sono quindi prevedibili.
Kylotan,

2
Per quanto riguarda la casualità, ogni mondo può avere il proprio valore di seme che viene utilizzato nei calcoli. per esempio. sin (x + seed) invece di sin (x), nel mio esempio sopra. Ogni seme diverso genererà un mondo diverso. E per quanto riguarda l'enorme foglio ... Non sono sicuro di quale rilevanza abbia. Non importa quanto o quanto poco generi o quando lo fai. Lo stato iniziale del mondo è definito dalla formula matematica e basta usare quella formula per scoprire quello stato come e quando ne hai bisogno.
Kylotan,

32

Questo tutorial che ho scritto anni fa potrebbe darti qualcosa di simile a quello che vuoi:

testo alternativo

Se si esegue la modifica dell'isola nell'ultimo passaggio, tende verso una singola massa terrestre che non raggiunge il bordo della mappa.


7
Grandi visualizzazioni!
zfedoran,

3
Ricordo di aver usato questo tutorial durante la tesi di laurea magistrale sulla simulazione di fenomeni naturali. Ho usato l'esempio "collina" per creare la cupola del cielo sul mio mondo 3D. Ottima introduzione al concetto di generazione del terreno.
C.McAtackney,

1
Pazzo, è fantastico! Non sapevo che qualcuno lo avesse mai usato davvero.
munifico

1
OH MIO DIO !!! L'ho usato anche in un progetto precedente ... il modo più semplice per generare terreno che abbia mai incontrato !!!
Guerra

15

Per creare una grande isola non è necessario generarla tutta in una volta. Costruirò le regioni in modo asincrono mentre le visiti.

Invece di usare una maschera per creare l'isola come descritto nell'articolo, una cosa che puoi fare è giocare con le lunghezze d'onda dell'ottava del rumore perlin per ottenere l'aspetto che stai cercando. Di solito, la prima ottava descrive la forma generale del terreno. Tutte le ottave successive aggiungono semplicemente ulteriori dettagli a grana fine. Pertanto, gioca con la lunghezza d'onda della prima ottava per controllare quanto saranno grandi le tue masse di terra. Se si desidera che la massa terrestre si trovi al centro, è possibile semplicemente ridurre la mappa dell'altezza di una quantità crescente man mano che ci si allontana dal centro e quindi normalizzare il rumore. Ad esempio, immagina di combinare questi due per creare la tua isola:

prima ottava dettagli

Questo articolo dovrebbe aiutare: http://freespace.virgin.net/hugo.elias/models/m_perlin.htm

Se vuoi conoscere infiniti mondi 3d e vari trucchi che puoi usare per cambiare l'aspetto del terreno giocando con l'ingresso e l'uscita del rumore, dai un'occhiata a questo articolo: http://http.developer.nvidia.com /GPUGems3/gpugems3_ch01.html

Potrebbe essere una lettura un po 'difficile se non si ha familiarità con la pipeline grafica e la programmazione dello shader.


Il tipo di effetto che voglio ottenere è qualcosa di simile a un 2d in basso nella mappa di Minecraft (non gioco) ... se avessi usato meno ottave, non avrei ancora bisogno di generare un enorme foglio di rumore del perlin? O potrei in qualche modo generarne solo una quantità molto piccola?
The Communist Duck,

Penso che potresti essere ancora un po 'confuso su come funziona il rumore perlin. È possibile generare blocchi di singoli blocchi 16x16 inviando la funzione agli offset delle coordinate xey per il rumore del perlin. Notare come la funzione PerlinNoise_2D (float x, float y) accetta le coordinate xey. In altre parole, genera rumore per alcune posizioni (x, y). Inoltre, generare meno ottave non equivale a cambiare la lunghezza d'onda delle ottave. Meno ottave => Dettaglio meno a grana fine. Lunghezza d'onda più lunga => ingrandimento maggiore.
zfedoran,

Inoltre, ecco un articolo con codice che mostra come implementare zoom / lunghezze d'onda più lunghe: dreamincode.net/forums/topic/66480-perlin-noise
zfedoran


7

Il rumore di Perlin e gli amici sono un buon punto di partenza, ma probabilmente vorrai fare un ulteriore passo avanti. La maggior parte dei generatori di rumore popolari ti darà risultati abbastanza poco interessanti. Al fine di rendere realistico il terreno, si desidera dare un'occhiata agli algoritmi che emulano gli effetti dell'erosione. Uno dei più avanzati simulatori del mondo di gioco là fuori - Dwarf Fortress - fa la simulazione dell'erosione come una delle fasi di costruzione del mondo.

Una delle soluzioni più interessanti che ho visto è stata descritta nell'articolo "Advanced Particle Deposition" nelle gemme di programmazione del gioco 7. Ce ne sono molte altre disponibili su Internet, quindi ci sono molte risorse da cui attingere (ad es. 1 o 2 ) .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.