Wie erstelle ich flächendeckende Geräusche für die Kartengenerierung?


16

Hey Leute, ich versuche herauszufinden, wie man tileable Fraktale in Code generiert (für Spielkarten, aber das ist irrelevant ). Ich habe versucht, das Solid Noise-Plug-in zu modifizieren, das mit GIMP geliefert wird (mit meinem äußerst begrenzten Verständnis dafür, wie Der Code funktioniert), aber ich kann meinen nicht zum korrekten Arbeiten bringen.

Mein bisher modifizierter Code (Java)

GIMPs Solid Noise-Modul, auf dem ich meinen Code aufbaue (C)

Das versuche ich zu erreichen, aber das bekomme ich

Wenn also jemand sehen kann, was ich falsch gemacht habe oder einen Vorschlag hat, wie ich es anders machen könnte, würde ich es sehr schätzen. Danke im Voraus. Und wenn ich zu viel frage oder nur ein großer Misserfolg im Leben ist, entschuldige ich mich.


versuchen Sie es mit bikubischer Interpolation statt bilinear? Ich habe keine Ahnung, ob das dein Problem ist, aber es sieht so aus.
Stephen Furlani

Antworten:


4

Ich folge Ihrem Code nicht genau, aber hier ist eine vereinfachte Beschreibung des Algorithmus, der den Effekt in etwa erzielt (basierend auf dem von Ihnen geposteten Bild).

Die folgende Erklärung ist nicht die superoptimierte Version, aber eine, die konzeptionell klar ist (hoffe ich). Sobald Sie es zum Laufen gebracht haben, können Sie es optimieren (tatsächlich ziemlich drastisch).

  1. Generieren Sie n Ebenen mit gleichmäßigem Zufallsrauschen (nur zufällige Graustufenpixel).
  2. Nun wird jedes dieser Pixel abgetastet, indem alle 1, 2, 4, 8, ... 2 ^ (n-1) Pixel abgetastet und die Zwischenpixel interpoliert werden. Jede Schicht ist glatter als die vorherige.
  3. Skalieren Sie diese nun mit einem Faktor von 1, 2, 4, 8 usw. Jede Ebene ist dunkler als die vorherige.
  4. Fügen Sie all diese zusammen.
  5. Normalisieren Sie, indem Sie jedes Pixel durch (1 + 2 + 4 + 8 + ... 2 ^ (n-1)) teilen.

Der schwierige Schritt ist der Abtast- und Interpolationsschritt. Angenommen, wir überspringen in der Ebene die Abtastung jedes m-ten Pixels. Hier ist die Grundidee für m> 1 (wenn m 1 ist, verwenden wir das Bild so wie es ist):

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)

Einige Tipps:

  • Das Ergebnis des obigen Algorithmus scheint etwas verwaschen zu sein. Sie können diesen Effekt reduzieren, indem Sie für alle Ebenen dieselbe Rauschebene verwenden oder das Bild anschließend kontrastverstärken.
  • Der obige Algorithmus verwendet eine lineare Interpolation, aber eine Kosinusinterpolation (eine Suche) liefert viel bessere Ergebnisse.
  • Machen Sie es möglich, Ihre Ebenen während aller Teile des Algorithmus separat zu betrachten. Auf diese Weise können Sie Fehler schnell beseitigen.

3

Es sieht so aus, als ob mein ursprünglicher Pastebin irgendwie abgelaufen ist. Daher kann ich meinen nicht funktionierenden Code nicht vergleichen, aber in meinem aktuellen Spiel habe ich den GIMP-Code erneut in Java übersetzt und es scheint nun gut zu funktionieren.

Wenn jemand beabsichtigt, diesen Code zu verwenden, würde ich empfehlen, den Konstruktor zu ändern, um die Einstellungsparameter (Detail und Größe) zu ändern, damit Sie es so machen können, wie Sie möchten. BEARBEITEN: Mir wurde klar, dass es bei meiner ursprünglichen Frage darum ging, die Kachelbarkeit zu verbessern. Denken Sie also daran, die Kachelbarkeit auf "wahr" zu setzen.

Code: http://pastebin.com/KsfZ99Xa

Beispiel: Perlin Generator Beispiel


2

Wir haben gerade die Java- und C-Versionen durchgesehen und einen kleinen Unterschied in der Art und Weise festgestellt, wie Sie die Rauschfunktion verwenden. Hier ist deins:

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

C-Code:

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

                                           (row - yoffset) / height));

Warum haben Sie sich entschieden, den Offset nicht zu subtrahieren? (col - xoffset) und (row - yoffset)

Ich wundere mich nur. Ich habe keine Zeit, den Code vollständig zu analysieren.

Hoffe das hilft.


xoffset und yoffset sind so zu berechnen, wie GIMP Bilder in Raster unterteilt, aber mein Programm funktioniert alle auf einer Kachel, sodass der x- und y-Versatz 0 wäre
Nick Badal

2

Ich weiß nicht, ob es helfen könnte, aber der folgende Trick hat mir geholfen:

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

Dieser Typ verwendet eine 4d-Rauschfunktion und gibt einfach xy-Werte von zwei Kreisen als xyzw-Werte für das 4d-Rauschen an. Das Ergebnis ist eine perfekte Schleife.

Hier ist die Idee (vereinfacht) für ein 1000 * 1000-Bild:

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

Ich empfehle die Verwendung des Diamantquadrat-Algorithmus , der auch als Plasma-Fraktal oder zufälliges Fraktal mit Mittelpunktverschiebung bezeichnet wird. Mit diesem Algorithmus ist es sehr einfach, die Kanten auf die gleichen Werte zu beschränken. Wenn Sie einen Wert für eine Kante generieren, kopieren Sie ihn auf die entsprechende Kante auf der anderen Seite. Dies ergibt eine perfekt gekachelte Karte.


0

Es gibt einen großen Artikel über die Geräuschentwicklung hier . Es ist kein Perlin-Rauschen, wie der Artikel behauptet (es ist eigentlich rosa Rauschen), aber es ist immer noch unglaublich nützlich zu verstehen, wie Rauschbilder erzeugt werden.

Um Ihre Frage tatsächlich zu beantworten: Um ein kachelbares Rauschbild zu erstellen, müssen Sie lediglich die "Kachelbarkeit" während der gesamten Generation beibehalten. Das heißt, wenn Rauschen geglättet wird, wird es geglättet, als würde es unendlich in alle Richtungen wiederholt - gekachelt.


0

Aus dem Screenshot schätze ich, dass nur die "großen" Ebenen generiert werden, weshalb das Rauschen zu regelmäßig erscheint und keine Details aufweist.

Das klingt vielleicht dumm, aber haben Sie versucht, die Variable "detail" (Zeile 16) zu erhöhen? In Ihrem Code ist es auf 1 gesetzt, was bedeutet, dass der Algorithmus vor dem Anhalten nur zwei Detailebenen generiert. Versuchen Sie es auf 8 zu erhöhen.


0

Schauen Sie sich auch Simplex Noise an , das von Ken Perlin entwickelt wurde, um einige Mängel von Perlin Noise zu beheben.

Ich habe an einer Implementierung von Simplex Noise für ein C ++ - Spiel gearbeitet. Es unterstützt 1D / 2D / 3D / 4D-Rauschen mit mehreren Oktaven. Im Moment ist die einzige eingebaute Textur Marmor, aber Sie könnten leicht mehr hinzufügen:

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

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.