Apa yang membuat tabel permutasi yang baik?


8

Saya menerapkan peningkatan kebisingan Perlin . Fitur utamanya untuk pengacakan adalah tabel permutasi hardcoded, yang pada dasarnya memberikan gradien acak tetapi dapat direproduksi pada sel-sel grid. Tabel permutasi hanyalah permutasi dari integer 0..255, dan biasanya tabel berikut (disalin langsung dari implementasi asli 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};

Untuk referensi, tambalan kecil yang diambil dari kebisingan yang dihasilkan oleh tabel ini terlihat seperti ini:

masukkan deskripsi gambar di sini

Namun, saya ingin kode menjadi sedikit lebih fleksibel dan memungkinkan tabel ini untuk di-reshuffle sehingga saya dapat membuat bidang kebisingan yang sama sekali baru (bukan hanya mengambil sampel pada offset yang berbeda). Tetapi tidak semua permutasi sama baiknya dikocok. Dalam kejadian yang tidak mungkin bahwa permutasi acak hanyalah array yang diurutkan dari 0ke 255, noise akan terlihat seperti ini sebagai gantinya:

masukkan deskripsi gambar di sini

Itu agak buruk. Tentu saja, pada kesempatan di, ini bukan kasus yang perlu saya khawatirkan. Tapi tentu saja, ini bukan satu-satunya permutasi yang menghasilkan artefak yang sangat mencolok. Permutasi terbalik yang diurutkan dan hampir diurutkan kemungkinan memiliki masalah yang sama. Jadi berapa banyak permutasi lain yang tidak cocok? Katakanlah kode akan digunakan dalam permainan populer untuk menghasilkan dunia acak di muka, itu masih akan mengganggu jika setiap dunia yang dihasilkan ke-100.000 akan terlihat dari jarak jauh biasa.1256!

Jadi pertanyaannya adalah, apa yang sebenarnya membuat tabel permutasi yang baik (atau buruk), dan bagaimana cara menilai kualitas tabel permutasi secara terprogram, sehingga saya dapat mengubah tabel sekali lagi jika saya menggulung "buruk" " meja?


Uji statistik untuk generator angka acak harus bermanfaat. Menghitung jumlah pasangan urutan (urutan terbalik) yang diharapkan mungkin merupakan tempat yang baik untuk memulai dengan sebuah tes. Makalah ini memiliki banyak referensi: csrc.nist.gov/groups/ST/toolkit/rng/documents/nissc-paper.pdf .
Daniel M Gessel

Jawaban:


4

Pertama-tama - angka tidak boleh muncul dua kali, itu tersirat karena kita berbicara tentang permutasi. Jadi mengisi tabel dengan fungsi acak (255) sederhana tidak akan berfungsi.

Kedua , Anda perlu memastikan bahwa tidak ada pola rekurensi dini:

Pertimbangkan nilai 1,2,3,4 - tabel permutasi 4,3,2,1 bukanlah yang sangat baik karena sifat sikliknya yang pendek, yaitu 1 -> 4, 4 -> 1. Begitu juga dengan 4,2 , 3,1 atau 1,2,3,4. Tabel optimal membawa Anda sepenuhnya melalui semua posisi: 3,1,4,2 atau 2,4,1,3.

Properti ini menjadi semakin penting saat Anda meningkatkan jumlah dimensi dan melakukan pencarian rekursif.

Namun pendekatan ini sendiri dapat membuat kelompok nilai yang terlalu mirip, yang mungkin atau mungkin tidak diinginkan, yang membawa saya ke poin berikutnya.

Ketiga , Ketika Anda menghasilkan tabel dengan properti non-siklik, Anda perlu melangkah melalui sisa indeks yang tidak ditetapkan secara acak. Bila memungkinkan membatasi jarak langkah acak di sini ke kisaran min dan maks tertentu, mis. 5..120 untuk menghindari kelompok yang dikelompokkan dari nilai yang sama. Angka-angka ini layak untuk dicoba.


Selamat Datang di Komputer Grafik SE! Kembali poin kedua Anda, saya melihat dekomposisi siklik tabel permutasi yang digunakan oleh Perlin. Ini terdiri dari beberapa siklus panjang {4, 121, 89, 12, 4, 15, 4, 6}, jadi ternyata itu cukup bagus? (Atau mungkin tidak dan tabel permutasi yang berbeda akan lebih "lebih baik"? Meskipun saya tidak yakin manusia dapat merasakan perbedaannya. Atau sebenarnya lebih baik memiliki beberapa siklus?) Saya tidak mengikuti poin ketiga Anda . Distribusi acak seragam apa? Dan apa jarak langkah yang Anda maksud?
Martin Ender

Terima kasih! Ya, kurasa itu cukup samar. Itu bertahun-tahun yang lalu saya bereksperimen dengan ini, jadi saya tidak ingat implementasi yang tepat, tetapi ketika Anda memiliki implementasi untuk generasi jalur yang optimal, harus menjadi jelas bahwa Anda memilih posisi acak dari apa yang tersisa dari indeks yang tidak digunakan - itu adalah panjang langkah acak yang saya rujuk. Saya memperbarui jawabannya
mhbuur

1

Satu kemungkinan adalah meminjam dari komunitas kriptografi dan, khususnya, substitusi 8-bit ke 8-bit yang digunakan dalam cipher AES / Rijndael. Tabel dan kode untuk menghasilkannya dapat ditemukan di wikipedia.

Saya kira itu, untuk menghasilkan hingga 256 tabel tambahan, Anda bisa melakukan sesuatu seperti:

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

(karena fungsi SBox sangat non-linear)

Karena itu, (dan tolong maafkan saya jika saya memiliki beberapa detail yang salah) di kehidupan sebelumnya saya menerapkan kebisingan Perlin menggunakan fungsi RNG / Hash yang relatif sederhana tetapi menemukan korelasi dalam X / Y / Z karena sederhana saya pemetaan 2 atau 3 dimensi ke nilai skalar bermasalah. Saya menemukan bahwa perbaikan yang sangat sederhana hanya menggunakan CRC, misalnya. sesuatu seperti

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

Mengingat intrinsik CRC dapat dibangun di dalam CPU HW, ini bisa menjadi pendekatan yang cepat.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.