Harita üretimi için tileable katı gürültü nasıl oluştururum?


16

Hey millet, ben kodda tileable fraktallar oluşturmak için nasıl anlamaya çalışıyorum (oyun haritaları için, ama bu ilgisiz ) GIMP ile gönderilen Katı Gürültü eklentisini değiştirmeye çalışıyorum (nasıl son derece sınırlı benim anlayışım ile) kod çalışır) ama benim düzgün çalışması için alamıyorum.

Şu ana kadar değiştirilmiş kodum (Java)

Kodumu dayandırdığım GIMP'in sağlam gürültü modülü (C)

İşte elde etmeye çalıştığım şey ama elde ettiğim şey bu

Herkes yanlış yaptığımı görebiliyorsa veya farklı bir şekilde nasıl yapabileceğime dair bir öneri varsa, bunu çok takdir ediyorum. Şimdiden teşekkürler. Ve eğer çok şey istiyorsam ya da hayatta büyük bir başarısızlık olursa özür dilerim.


bilinear yerine bikubik enterpolasyon kullanmayı deneyin ? Sorunun bu olup olmadığı hakkında hiçbir fikrim yok, ama öyle görünüyor.
Stephen Furlani

Yanıtlar:


4

Kodunuzu tam olarak takip etmiyorum, ancak burada kabaca efekti elde edecek algoritmanın basitleştirilmiş bir açıklaması (yayınladığınız görüntüye dayanarak).

Aşağıdaki açıklama süper optimize versiyonu değil, kavramsal olarak net olanıdır (umarım). Çalıştırdıktan sonra, optimize edebilirsiniz (oldukça büyük ölçüde).

  1. Düzgün rastgele gürültü (sadece rastgele gri tonlamalı pikseller) n katmanları oluşturun.
  2. Şimdi bunların her birini her 1, 2, 4, 8, ... 2 ^ (n-1) pikseli örnekleyerek ve ara pikselleri enterpolasyonlayarak örnekleyin. Her katman bir öncekinden daha pürüzsüzdür.
  3. Şimdi bunları 1, 2, 4, 8 vb. Faktörlerle ölçeklendirin. Her katman bir öncekinden daha koyudur.
  4. Tüm bunları bir araya getirin.
  5. Her pikseli (1 + 2 + 4 + 8 + ... 2 ^ (n-1)) ile bölerek normalleştirin.

Zor adım örnekleme ve enterpolasyon aşamasıdır. Her bir mth pikselden örnek atlama katmanında olduğumuzu varsayalım. İşte m> 1 için temel fikir (m 1 ise, görüntüyü olduğu gibi kullanırız):

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)

Birkaç ipucu:

  • Yukarıdaki algoritmanın sonucu biraz soluk görünebilir. Tüm katmanlar için aynı gürültü katmanını kullanarak bu efekti azaltabilir veya sonrasında kontrastı artırabilirsiniz.
  • Yukarıdaki algoritma doğrusal enterpolasyon kullanır, ancak kosinüs enterpolasyonu (bir arama yapın) çok daha iyi sonuçlar verir.
  • Algoritmanın tüm bölümleri sırasında katmanlarınıza ayrı ayrı bakmayı mümkün kılın. Bu, hataları hızlı bir şekilde temizlemenize yardımcı olacaktır.

3

Orijinal macunumun bir şekilde süresi dolmuş gibi görünüyor, bu yüzden çalışmayan kodumu karşılaştırmanın bir yolu yok, ancak mevcut oyunumda GIMP kodunu tekrar java'ya çevirdim ve şimdi iyi çalışıyor gibi görünüyor.

Herkes bu kodu kullanmayı planlıyorsa, ayar parametrelerini (ayrıntı ve boyut) değiştirmek için yapıcıyı değiştirmenizi tavsiye ederim, böylece istediğiniz şekilde çalışmasını sağlayabilirsiniz. EDIT: Orijinal sorumun tileable yapmak hakkında olduğunu fark ettim, bu yüzden tilable doğru doğru ayarlamak unutmayın!

Kodu: http://pastebin.com/KsfZ99Xa

Misal: perlin jeneratörü örneği


2

Sadece Java ve C sürümleri arasında dolaştı ve gürültü işlevini kullanma biçiminizde küçük bir fark fark ettim. İşte sizinkiler:

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

C kodu:

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

                                           (row - yoffset) / height));

Ofseti çıkarmamayı neden seçtiniz? (col - xoffset) ve (satır - yoffset)

Sadece merak ediyorum. Kodun tam bir analizini yapmak için zamanım yok.

Bu yardımcı olur umarım.


xoffset ve yoffset, GIMP'in görüntüleri ızgaralara ayırma biçimini hesaplamak içindir, ancak programımın hepsi tek bir döşemede çalışıyor, böylece x ve y ofseti 0 olacaktır
Nick Badal

2

Yardımcı olabilir mi bilmiyorum ama aşağıdaki numara benim için bir tedavi yaptı:

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

Bu adam 4d gürültü fonksiyonu kullanıyor ve sadece 4d gürültü için xyzw değerleri olarak iki dairenin xy değerlerini sağlıyor. Sonuç mükemmel bir döngü.

1000 * 1000 resim için fikir (basitleştirilmiş):

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;

  }
}

1

Plazma fraktal veya rastgele orta nokta deplasman fraktal olarak da bilinen elmas kare algoritmasını kullanmanızı öneririm . Bu algoritmayı kullanarak kenarların aynı değerlere sahip olmasını kısıtlamak çok kolaydır. Bir kenar için değer oluşturduğunuzda, diğer kenardaki ilgili kenara kopyalayın. Bu mükemmel bir döşeme haritası verir.


0

Burada gürültü üretimi ile ilgili harika bir makale var . Makalenin iddia ettiği gibi Perlin gürültüsü değil (aslında pembe gürültü), ancak gürültü görüntülerinin nasıl üretildiğini anlamak hala inanılmaz derecede yararlı.

Yani, aslında sorunuzu cevaplamak için: bir tileable gürültü görüntü yapmak için, sadece nesil boyunca "tileability" tutmak gerekir. Yani, gürültü yumuşatıldığında, her yönden sonsuz bir şekilde tekrarlanmış gibi döşenir.


0

Ekran görüntüsüne göre, sanırım sadece "büyük" katmanlar üretiliyor, bu yüzden gürültü çok düzenli görünüyor ve detaylardan yoksun.

Bu aptalca gelebilir, ancak "ayrıntı" değişkenini (satır 16) artırmayı denediniz mi? Kodunuzda 1 olarak ayarlanır, yani algoritma durmadan önce yalnızca iki ayrıntı katmanı oluşturur. 8 gibi bir şeye yükseltmeyi deneyin.


0

Ayrıca Simplex Noise'a da göz atmalısınız Perlin gürültüsünün bazı eksikliklerini gidermek için Ken Perlin tarafından geliştirilen .

Bir C ++ oyunu için Simplex Noise uygulaması üzerinde çalışıyorum. Çoklu oktav 1D / 2D / 3D / 4D gürültüyü destekler. Şu anda, tek yerleşik doku mermerdir, ancak daha fazlasını kolayca ekleyebilirsiniz:

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.