Jak utworzyć stały hałas z kafelków podczas generowania mapy?


16

Hej, próbuję wymyślić, jak wygenerować fraktale z kafelków w kodzie (dla map gier, ale to nie ma znaczenia ) Próbowałem zmodyfikować wtyczkę Solid Noise dostarczaną z GIMP (z moim bardzo ograniczonym rozumieniem, w jaki sposób kod działa), ale nie mogę sprawić, by mój działał poprawnie.

Mój dotychczas zmodyfikowany kod (Java)

Moduł stałego szumu GIMP, od którego opieram swój kod na (C)

Oto, co próbuję osiągnąć, ale właśnie to otrzymuję

Więc jeśli ktoś może zobaczyć, co zrobiłem źle, lub ma sugestię, jak mógłbym to zrobić inaczej, byłbym bardzo wdzięczny. Z góry dziękuję. A jeśli pytam o wiele, a jeśli po prostu wielką porażkę w życiu, przepraszam.


spróbuj użyć interpolacji dwuububowej zamiast dwuliniowej? Nie mam pojęcia, czy to twój problem, ale WYGLĄDA tak, jak jest.
Stephen Furlani,

Odpowiedzi:


4

Nie podążam dokładnie za twoim kodem, ale tutaj jest uproszczony opis algorytmu, który z grubsza osiągnie efekt (na podstawie opublikowanego obrazu).

Poniższe wyjaśnienie nie jest wersją superoptymalizowaną, ale jest koncepcyjnie jasne (mam nadzieję). Po uruchomieniu możesz go zoptymalizować (w rzeczywistości dość drastycznie).

  1. Wygeneruj n warstw jednolitego losowego szumu (tylko losowe piksele w skali szarości).
  2. Teraz próbkuj każdy z nich, próbkując co 1, 2, 4, 8, ... 2 ^ (n-1) pikseli i interpolując piksele pośrednie. Każda warstwa jest gładsza niż poprzednia.
  3. Teraz skaluj je ze współczynnikiem 1, 2, 4, 8 itd. Każda warstwa jest ciemniejsza niż poprzednia.
  4. Dodaj je wszystkie razem.
  5. Normalizuj, dzieląc każdy piksel za pomocą (1 + 2 + 4 + 8 + ... 2 ^ (n-1)).

Trudnym krokiem jest etap próbkowania i interpolacji. Załóżmy, że w warstwie pomijamy próbkowanie co m-ty piksel. Oto podstawowy pomysł na m> 1 (jeśli m wynosi 1, używamy obrazu w stanie, w jakim się znajduje):

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)

Kilka wskazówek:

  • Wynik powyższego algorytmu może wydawać się nieco wyprany. Możesz zredukować ten efekt, stosując tę ​​samą warstwę szumu dla wszystkich warstw, lub później poprawić kontrast obrazu.
  • Powyższy algorytm wykorzystuje interpolację liniową, ale interpolacja cosinus (wyszukiwanie) daje znacznie lepsze wyniki.
  • Umożliwiaj przeglądanie warstw osobno podczas wszystkich części algorytmu. Pomoże to w szybkim usuwaniu błędów.

3

Wygląda na to, że mój oryginalny pastebin jakoś wygasł, więc nie mam możliwości porównania mojego niedziałającego kodu, ale w mojej obecnej grze przeszedłem i ponownie przetłumaczyłem kod GIMP na java i wydaje się, że teraz działa dobrze.

Jeśli ktoś planuje użyć tego kodu, zaleciłbym modyfikację konstruktora, aby zmodyfikować parametry ustawienia (szczegóły i rozmiar), abyś mógł ustawić go tak, jak chcesz. EDYCJA: Zdałem sobie sprawę, że moje oryginalne pytanie dotyczyło uczynienia go kafelkowym, więc pamiętaj, aby ustawić tilable na true!

Kod: http://pastebin.com/KsfZ99Xa

Przykład: przykład generatora perlin


2

Przejrzałem tylko wersje Java i C i zauważyłem niewielką różnicę w sposobie korzystania z funkcji szumu. Oto twoje:

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

Kod C:

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

                                           (row - yoffset) / height));

Dlaczego zdecydowałeś się nie odejmować przesunięcia? (col - xoffset) i (row - yoffset)

Zastanawiam się. Nie mam czasu na pełną analizę kodu.

Mam nadzieję że to pomoże.


xoffset i yoffset mają obliczyć sposób, w jaki GIMP dzieli obrazy na siatki, ale mój program działa na jednym kafelku, więc przesunięcie xiy wynosiłoby 0
Nick Badal

2

Nie wiem, czy to może pomóc, ale następująca sztuczka okazała się dla mnie przyjemnością:

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

Ten facet używa funkcji szumu 4d i po prostu podaje wartości xy dwóch kół jako wartości xyzw dla szumu 4d. Rezultat jest perfekcyjny.

Oto pomysł (uproszczony) na zdjęcie 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;

  }
}

1

Polecam użycie algorytmu diamentowego kwadratu , znanego również jako fraktal plazmy lub fraktal przemieszczenia losowego punktu środkowego. Za pomocą tego algorytmu bardzo łatwo jest ograniczyć krawędzie, aby miały te same wartości. Gdy generujesz wartość krawędzi, skopiuj ją do odpowiedniej krawędzi po drugiej stronie. Daje to idealnie kafelkową mapę.


0

Jest to świetny artykuł o emisji hałasu tutaj . Jak twierdzi artykuł, nie jest to szum Perlina (właściwie różowy szum), ale nadal niezwykle przydatne jest zrozumienie, w jaki sposób generowane są obrazy szumu.

Tak więc, aby faktycznie odpowiedzieć na twoje pytanie: aby stworzyć obraz szumu, który trzeba kafelkować, wystarczy zachować „kafelkowanie” przez całe pokolenie. Oznacza to, że gdy hałas jest wygładzany, wygładzasz go tak, jakby powtarzał się w nieskończoność we wszystkich kierunkach - kafelkami.


0

Na podstawie zrzutu ekranu sądzę, że generowane są tylko „duże” warstwy, dlatego hałas wydaje się zbyt regularny i pozbawiony szczegółów.

Może to zabrzmieć głupio, ale czy próbowałeś zwiększyć zmienną „szczegółowość” (linia 16)? W kodzie jest on ustawiony na 1, co oznacza, że ​​algorytm wygeneruje tylko dwie warstwy szczegółów przed zatrzymaniem. Spróbuj zwiększyć go do około 8.


0

Powinieneś także spojrzeć na Simplex Noise , który został opracowany przez Kena Perlina, aby naprawić niektóre niedociągnięcia związane z hałasem Perlina.

Pracowałem nad implementacją Simplex Noise do gry w C ++. Obsługuje wielooktawowy szum 1D / 2D / 3D / 4D. W tej chwili jedyną wbudowaną teksturą jest marmur, ale możesz z łatwością dodać więcej:

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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.