Cosa rende una buona tabella di permutazione?


8

Sto implementando un rumore Perlin migliorato . La sua caratteristica chiave per la randomizzazione è la tabella di permutazione codificata, che fornisce gradienti essenzialmente casuali ma riproducibili alle celle della griglia. La tabella di permutazione è solo una permutazione degli interi 0..255ed è generalmente la seguente tabella (copiata direttamente dall'implementazione originale di Perlin):

{151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7,
225, 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247,
120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33,
88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134,
139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220,
105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 54, 65, 25, 63, 161, 1, 216, 80,
73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86,
164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123, 5, 202, 38,
147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189,
28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101,
155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232,
178, 185, 112, 104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12,
191, 179, 162, 241, 81, 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181,
199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236,
205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180};

Per riferimento, una piccola patch disegnata dal rumore generato da questa tabella è simile alla seguente:

inserisci qui la descrizione dell'immagine

Tuttavia, vorrei che il codice fosse un po 'più flessibile e consentissi di rimescolare questa tabella in modo da poter creare un campo noise completamente nuovo (invece di campionarlo con un offset diverso). Ma non tutte le permutazioni sono ugualmente ben mescolate. Nel caso improbabile che la permutazione casuale sia solo l'array ordinato da 0a 255, il rumore sarebbe invece simile a questo:

inserisci qui la descrizione dell'immagine

È un po 'brutto. Certo, alla possibilità di1 in 256!, questo non è un caso di cui devo preoccuparmi. Ma sicuramente, questa non è l'unica permutazione che produce artefatti molto evidenti. Le permutazioni inverse e quasi ordinate avrebbero probabilmente gli stessi problemi. Quindi quante altre permutazioni sono inadatte? Supponiamo che il codice venga utilizzato in un gioco popolare per generare un mondo casuale in anticipo, sarebbe comunque fastidioso se ogni 100.000esimo mondo generato sembrasse remoto.

Quindi la domanda è: cosa rende esattamente una tabella di permutazione buona (o cattiva) e come posso valutare la qualità di una tabella di permutazione a livello di codice, in modo tale da poter rimescolare la tabella ancora una volta nell'improbabile evento in cui lancio un "cattivo " tavolo?


I test statistici per i generatori di numeri casuali dovrebbero essere utili. Il calcolo del numero previsto di coppie in ordine (ordine inverso) potrebbe essere un buon punto di partenza con un test. Questo documento ha molti riferimenti: csrc.nist.gov/groups/ST/toolkit/rng/documents/nissc-paper.pdf .
Daniel M Gessel,

Risposte:


4

Prima di tutto - un numero non deve comparire due volte, ciò è implicito poiché stiamo parlando di permutazioni. Quindi riempire la tabella con una semplice funzione casuale (255) non funzionerà.

In secondo luogo , è necessario assicurarsi che non vi siano schemi di ricorrenza prematura:

Considera i valori 1,2,3,4 - la tabella di permutazione 4,3,2,1 non è molto buona a causa delle sue brevi proprietà cicliche, cioè 1 -> 4, 4 -> 1. Allo stesso modo con 4,2 , 3,1 o ​​1,2,3,4. Le tabelle ottimali ti portano in tutte le posizioni: 3,1,4,2 o 2,4,1,3.

Questa proprietà diventa sempre più importante quando si aumenta il numero di dimensioni e si eseguono ricerche ricorsive.

Tuttavia, questo approccio da solo può creare gruppi di valori troppo simili, che possono o meno essere desiderati, il che mi porta al punto successivo.

In terzo luogo , quando si genera una tabella con proprietà non cicliche, è necessario scorrere casualmente gli indici non assegnati rimanenti. Se possibile, limitare qui la distanza casuale del passo a un determinato intervallo minimo e massimo, ad esempio 5..120 per evitare gruppi raggruppati di valori simili. Vale la pena sperimentare questi numeri.


Benvenuti in Computer Graphics SE! Per quanto riguarda il tuo secondo punto, ho osservato la decomposizione ciclica della tabella di permutazione usata da Perlin. Consiste in più cicli di lunghezze {4, 121, 89, 12, 4, 15, 4, 6}, quindi apparentemente è abbastanza buono? (O forse non lo è e una diversa tabella di permutazione sarebbe persino "migliore"? Anche se non sono sicuro che un essere umano possa percepire la differenza. O in realtà è meglio avere più cicli?) Non sto seguendo il tuo terzo punto . Una distribuzione casuale uniforme di cosa? E quale distanza del passo intendi?
Martin Ender,

Grazie! Sì, immagino fosse abbastanza criptico. È stato anni fa che ho sperimentato questo, quindi non ricordo l'esatta implementazione, ma quando hai l'implementazione per la generazione del percorso ottimale, dovrebbe diventare evidente che scegli posizioni casuali di ciò che resta degli indici inutilizzati - è quel passo casuale a cui mi riferisco. Ho aggiornato la risposta
mhbuur il

1

Una possibilità potrebbe essere quella di prendere in prestito dalla comunità crittografica e, in particolare, la sostituzione da 8 a 8 bit utilizzata nel codice AES / Rijndael. La tabella e il codice per generarlo sono disponibili su Wikipedia.

Immagino che, al fine di generare fino a 256 tabelle aggiuntive, potresti semplicemente fare qualcosa del tipo:

Func(U8 input, U8 TableNum) = SBox( (TableNum + Sbox(input)) Mod256 )

(poiché la funzione SBox è abbastanza non lineare)

Detto questo, (e per favore perdonami se ho sbagliato alcuni dei dettagli) in una vita passata ho implementato il rumore Perlin usando una funzione RNG / Hash relativamente semplice ma ho trovato la correlazione in X / Y / Z a causa del mio semplice la mappatura di 2 o 3 dimensioni su un valore scalare era problematica. Ho scoperto che una soluzione molto semplice era solo quella di utilizzare un CRC, ad es. qualcosa di simile a

InputToRNGHash = CRC(Z xor CRC( Y xor CRC(X))). 

Dato che i CRC intrinseci possono essere integrati nella CPU HW, questo può essere un approccio rapido.

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.