Bagaimana cara membuat noise solid tileable untuk pembuatan peta?

16

Hai teman-teman, saya mencoba mencari cara untuk menghasilkan fraktal ubin dalam kode (untuk peta game, tapi itu tidak relevan ) Saya telah mencoba untuk memodifikasi plug-in Solid Noise yang dikirimkan dengan GIMP (dengan pemahaman saya yang sangat terbatas tentang bagaimana kode bekerja) tetapi saya tidak bisa mendapatkan milik saya untuk bekerja dengan benar.

Kode saya yang dimodifikasi sejauh ini (Jawa)

Modul kebisingan padat GIMP yang mendasari kode saya dari (C)

Inilah yang ingin saya capai tetapi inilah yang saya dapatkan

Jadi jika ada yang bisa melihat kesalahan saya, atau memiliki saran bagaimana saya bisa melakukannya secara berbeda, saya akan sangat menghargainya. Terima kasih sebelumnya. Dan jika saya meminta banyak atau jika hanya kegagalan besar dalam hidup, saya minta maaf.

Nick Badal
sumber
coba gunakan interpolasi bikubik alih-alih bilinear? Saya tidak tahu apakah itu masalah Anda, tetapi sepertinya memang begitu.
Stephen Furlani

Jawaban:

4

Saya tidak mengikuti kode Anda dengan tepat, tetapi di sini ada deskripsi yang disederhanakan dari algoritma yang kira-kira akan mencapai efeknya (berdasarkan gambar yang Anda posting).

Penjelasan berikut ini bukan versi super dioptimalkan, tetapi adalah salah satu yang jelas secara konsep (saya harap). Setelah Anda menjalankannya, Anda dapat mengoptimalkannya (cukup drastis, sebenarnya).

  1. Hasilkan n lapisan noise acak yang seragam (hanya piksel skala abu-abu acak).
  2. Sekarang sampel masing-masing dengan sampling setiap, 1, 2, 4, 8, ... 2 ^ (n-1) piksel, dan interpolasi piksel menengah. Setiap lapisan lebih halus dari yang sebelumnya.
  3. Sekarang skala ini dengan faktor 1, 2, 4, 8, dll. Setiap lapisan lebih gelap dari yang sebelumnya.
  4. Tambahkan semua ini bersama-sama.
  5. Normalisasikan dengan membagi setiap piksel dengan (1 + 2 + 4 + 8 + ... 2 ^ (n-1)).

Langkah yang sulit adalah langkah pengambilan sampel dan interpolasi. Misalkan kita berada di layer melewatkan sampling setiap m-th pixel. Ini adalah ide dasar untuk m> 1 (jika m adalah 1, kita menggunakan gambar apa adanya):

for each pixel x and y
   left_sample_coord = m *(x / m) //(integer division, automatically truncated)
   right_sample_coord = (left_sample_point + m) % image_width
   top_sample_point = m*(y / m) 
   bottom_sample_coord = (top_sample_point + m) % image_height

   horizontal_weight = (x - left_sample_point) / (m - 1)
   vertical_weight = (y - top_sample_point) / (m - 1)

   sample_top_left = image(left_sample_coord, top_sample_point)
   //and the same for the other four corners

   //now combine the top two points
   top_interpolate = sample_top_left * horizontal_weight + sample_top_right * (1-horizontal_weight)

  //now combine the bottom two points
  bottom_interpolate = sample_bottom_left * horizontal_weight + sample_bottom_right * (1-horizontal_weight)

  //and combine these two last obtained values

  smooth_noise(x, y) = top_interpolate * vertical_weight  + bottom_interpolate * (1 - vertical_weight)

Beberapa tips:

  • Hasil dari algoritma di atas mungkin tampak agak pudar. Anda dapat mengurangi efek ini dengan menggunakan lapisan noise yang sama untuk semua lapisan, atau meningkatkan kontras gambar setelahnya.
  • Algoritma di atas menggunakan interpolasi linier, tetapi interpolasi kosinus (melakukan pencarian) memberikan hasil yang jauh lebih baik.
  • Memungkinkan untuk melihat layer Anda secara terpisah selama semua bagian dari algoritma. Ini akan membantu Anda membersihkan bug dengan cepat.
Herman Tulleken
sumber
3

Sepertinya pastebin asli saya kedaluwarsa, jadi saya tidak punya cara untuk membandingkan kode non-kerja saya, tetapi pada permainan saya saat ini saya melaluinya dan menerjemahkan kode GIMP ke dalam java lagi dan sepertinya berfungsi dengan baik sekarang.

Jika ada yang berencana menggunakan kode ini, saya akan merekomendasikan memodifikasi konstruktor untuk memodifikasi parameter pengaturan (detail dan ukuran) sehingga Anda dapat membuatnya berfungsi seperti yang Anda inginkan. EDIT: Saya menyadari pertanyaan awal saya adalah tentang membuatnya tileable, jadi ingatlah untuk mengatur tilable menjadi true!

Kode: http://pastebin.com/KsfZ99Xa

Contoh: contoh generator perlin

Nick Badal
sumber
2

Hanya membaca sekilas versi Java dan C dan memperhatikan sedikit perbedaan dalam cara Anda menggunakan fungsi noise. Ini milikmu:

int val = Math.abs((int) Math.floor(255.0 * noise(((double)col/(double)width), ((double)row/(double)height))));

Kode C:

val = (guchar) floor (255.0 * noise ((col - xoffset) / width,

                                           (row - yoffset) / height));

Mengapa Anda memilih untuk tidak mengurangi offset? (col - xoffset) dan (baris - yoffset)

Hanya ingin tahu. Saya tidak punya waktu untuk melakukan analisis kode secara lengkap.

Semoga ini membantu.

Nailer
sumber
xoffset dan yoffset adalah untuk menghitung cara GIMP membagi gambar menjadi kisi-kisi, tetapi program saya semua bekerja pada satu ubin sehingga offset x dan y adalah 0
Nick Badal
2

Saya tidak tahu apakah itu bisa membantu tetapi trik berikut ini berhasil bagi saya:

http://www.gamedev.net/blog/33/entry-2138456-seamless-noise/

Orang ini menggunakan fungsi noise 4d dan hanya memberikan nilai xy dari dua lingkaran sebagai nilai xyzw untuk noise 4d. Hasilnya adalah perulangan sempurna.

Berikut adalah ide (disederhanakan) untuk gambar 1000 * 1000:

for(i = 0;i < 1000; i++){

  for(j = 0; j < 1000; j++){

    nx = cos((i/1000) * 2 * PI);
    ny = cos((j/1000) * 2 * PI);
    nz = sin((i/1000) * 2 * PI);
    nw = sin((j/1000) * 2 * PI);

    looped_noise = noise_4D( nx, ny, nz, nw, octaves, persistence, lacunarity, blah...);
    noise_buffer[(i*1000)+j] = looped_noise;

  }
}
Okr
sumber
1

Saya sarankan Anda menggunakan algoritma berlian-persegi , juga dikenal sebagai fraktal plasma atau fraktal perpindahan titik tengah acak. Dengan menggunakan algoritma ini, sangat mudah untuk membatasi tepi untuk memiliki nilai yang sama. Saat Anda menghasilkan nilai untuk tepi, salin ke tepi yang sesuai di sisi lain. Ini menghasilkan peta ubin sempurna.

drxzcl
sumber
0

Ada artikel bagus tentang generasi kebisingan di sini . Ini bukan Perlin noise seperti yang diklaim artikel (sebenarnya pink noise), tetapi masih sangat berguna untuk memahami bagaimana gambar noise dihasilkan.

Jadi, untuk benar-benar menjawab pertanyaan Anda: untuk membuat gambar noise tileable, Anda hanya perlu menjaga "tileability" sepanjang generasi. Artinya, ketika suara dihaluskan, Anda melicinkannya seolah diulang tanpa batas ke segala arah - ubin.

Lupakan
sumber
0

Dari tangkapan layar, dugaan saya adalah hanya lapisan "besar" yang dihasilkan, itulah sebabnya suara muncul terlalu teratur dan kurang detail.

Ini mungkin terdengar bodoh, tetapi apakah Anda mencoba meningkatkan variabel "detail" (baris 16)? Dalam kode Anda, ini diatur ke 1, yang berarti algoritma hanya akan menghasilkan dua lapisan detail sebelum berhenti. Coba tingkatkan menjadi sekitar 8.

Pengguna tidak ditemukan
sumber
0

Anda juga harus melihat Simplex Noise , yang dikembangkan oleh Ken Perlin untuk memperbaiki beberapa kekurangan kebisingan Perlin.

Saya telah mengerjakan implementasi Simplex Noise untuk game C ++. Mendukung multi-oktaf 1D / 2D / 3D / 4D noise. Saat ini, satu-satunya tekstur bawaan adalah marmer, tetapi Anda dapat dengan mudah menambahkan lebih banyak:

(http://code.google.com/p/battlestar-tux/source/browse/trunk/src/lib/procedural/)

i_grok
sumber