Brauche hilfe bei Perlin Noise :(
Übersicht

PhillipKBetreff: Brauche hilfe bei Perlin Noise :( |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Heyho Community ![]() Ich bastel mir grade eine Minecraft ähnliche map und möchte gerne Perlin noise zur erstellung nutzen. Da ich mich noch nie damit befasst habe, hab ich mir gestern die ganze zeit Hilfe dazu durchgelesen und Tutorials durchgeschaut. Leider bin ich ein wenig auf dem Holzweg, mein Code klappt nur teilweise. Die Codesnippets habe ich hieraus übersetzt: How to Use Perlin Noise in your games Ich glaube, ich habe irgendwo ein-zwei fehler bei der Int-rundung gemacht ![]() Zitat: int sample_i0 = (i / samplePeriod) * samplePeriod;
Dazu die bemerkung der Seite: Zitat: Note that the line:
Zitat: int sample_i0 = (i / samplePeriod) * samplePeriod;
is not the same as Zitat: int sample_i0 = i; because the division automatically floors the result to give an integer, so that sample_i0 is the largest multiple of the samplePeriod dmaller than i. For example, if i is 7 and samplePeriod is 3, then sample_i0 is 6. Den fehler *vermute* ich in der Funktion 'Generate Smooth Noise' - es scheint, als würde das Vertikale Smoothing nicht funktionieren (das Ergebnis sieht schon ein wenig nach Perlin noise aus, aber man erkennt ganz klar Vertikale linien, die vielleicht nicht gesmoothed wurden.. ![]() BlitzMax: [AUSKLAPPEN] SuperStrict Anmerkung: Ich nutze ein Codesnippet aus dem Code Archiv um mir die Mikro-sekundenzeit anzeigen zu lassen. Das Type ist win-only :3 Generiert wird ein Perlin-Noise array der dann mit seinen werten als Pixels in eine Pixmap eingetragen wird. Diese pixmap wird angezeigt. Größe ist per PFEIL HOCH und PFEIL RUNTER wählbar (exponent von 2 -> standartmäßig ist die höhe/breite auf 512x512) Interpolationsmethode wechseln geschieht auf ENTER. Interpolate Methode 1 ist Linear, Methode 2 *sollte* Cosine_Interpolate sein. MausRad stellt die Oktave'n zahl hoch/runter mit der GeneratePerlinNoise() aufgerufen wird. Das ganze ist nur ein Test, deshalb etwas unsortiert ![]() Sieht jemand meinen Denkfehler? Ich habe das Thema leider noch nicht genug verstanden, um selbst an den Werten rumzuspielen. Aber solangsam dreh ich durch, nach mehrmaligen durchgehen scheint alles 1zu1 auf Blitzmax übertragen worden zu sein :3 Bitte um hilfe :3 Gruß, PhillipK |
||
![]() |
XeresModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
Code: [AUSKLAPPEN] int sample_i0 = (i / samplePeriod) * samplePeriod;
Das funktioniert so auch in BlitzMax, gesetzt dem Fall, samplePeriod ist Float: BlitzMax: [AUSKLAPPEN] SuperStrict Doku - Type balancing hat Folgendes geschrieben: BlitzMax decides the result type by balancing the argument types. Both arguments are then converted to the result type before the operator is applied.
The rules governing type balancing are:
Lange Rede, kurzer Sinn: Du musst dir sicher sein, die richtigen Datentypen zu verwenden, um die richtigen Rundungen zu erreichen. |
||
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus THERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld) |
![]() |
Noobody |
![]() Antworten mit Zitat ![]() |
---|---|---|
@Xeres: Eigentlich ist es andersrum - das funktioniert nur, wenn i und samplePeriod beides Integer sind ![]() @PhillipK: Die Abrundungsrechnung ist korrekt, das Problem liegt woanders. vertical_blend und horizontal_blend sind als Integer deklariert (bzw. sind sie gar nicht deklariert und werden deshalb vom Compiler als Integer behandelt), dabei müssten es beides Floats sein. Wenn man diese zwei abändert, funktioniert der Code. Allerdings müsste man anmerken, dass die von dir verlinkte Seite ein wenig... unkonventionell vorgeht. Perlin Noise beginnt normalerweise mit der Oktave mit der grössten Wellenlänge und addiert mit steigender Oktavenzahl Rauschen mit höherer Frequenz und tieferer Amplitude. Der verlinkte Artikel aber beginnt mit der Oktave mit der kleinsten Wellenlänge und addiert mit steigender Oktavenzahl tiefere Frequenzen obenauf. Auch sonst scheint der Code ein paar seltsame Dinge zu machen (zumindest anders, als ich das bisher kannte); ich würde daher diesen Artikel empfehlen. Ich glaube, so ziemlich jeder, der mal mit Perlin Noise zu tun hatte, ist irgendwann mal auf diese Seite gestossen ![]() |
||
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun |
PhillipK |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
@Noobody:
Aaah die Seite ![]() Gestern habe ich mich bereits an diese Seite rangewagt. Allerdings hatte ich ohne grobes wissen über Perlin noise echte schwierigkeiten, da durchzusteigen. Zumal mein englisch auch zu wünschen übrig lässt. Allerdings wollte ich grade (nachdem ich ein bisschen frisch luft schnappen war) nochmal genau diese Seite zur hilfe nehmen *g* Garnicht deklariert? Bin ich nun bescheuert? :O Ich habe mir angewöhnt, für codesnippets wo es auf die geschwindigkeit ankommt, jede Variable vor den For schleifen zu deklarieren. Grade wenn es 2 For's verschachtelt sind, gibt es teilweise enorme variablen-initialisierungen. Ich weiß zwar nicht, ob das in Blitzmax nicht evtl vorher unterbunden wird oder ob tatsächlich ständig neuer speicher belegt wird, aber so finde ich persönlich es schöner. BlitzMax: [AUSKLAPPEN] Local sample_x0:Int, sample_x1:Int, horizontal_blend:Int Aber hier habe ich tatsächlich geschlampt. Vertical_blend ist float, horizontal_blend ist int. Mal schauen, ob ich es auch als "funktionierenden" code hinbekomme, um, falls meine weitere Exkursion ins Thema Perlin Noise heute fehlschlägt, wenigstens ein kleines erfolgserlebnis zu haben ![]() ----------- Mal ne oberflächlichere Frage: Ich plane grade eine Welt mit etwa 256x256x256 blöcken zu erstellen. (Minecraft Style) Pro ebene wollte ich den 'kontrast' der 2d Map erhöhen, aber den selben Random-seed verwenden. Sodass ich mir kleinere Berge und täler rendern lassen kann und der Rest ein Solider block ist. Ist da perlin noise zu empfehlen? Wenn ich es richtig verstanden habe, kann man durch die schicken parameter auch generelle Strukturen nachempfinden, so zb ein eher Hügeligeres Land, oder aber ein flaches tal was zb nur 3-4 Blöcke hoch ist. Danke schonmal an euch beiden fürs drübergucken ![]() |
||
PhillipK |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Okay mittlerweile Tag 3 des Verzweifelns.
Ich habe nocheinmal den artikel den Noobody vorgeschlagen hat vorgenommen und durchgearbeitet. Solangsam verstehe ich, was genau bei dem Perlin noise algorythmus funktioniert. Problem an der ganzen geschichte ist nun der Random generator. Ich habe schon viele ideen durchgeprobiert, um einen eigenen Random-generator zu schreiben. Letzten endes hat nichts funktioniert. Auf der seite steht folgende funktion: Code: [AUSKLAPPEN] function PerlinNoise_2D(float x, float y)
total = 0 p = persistence n = Number_Of_Octaves - 1 loop i from 0 to n frequency = 2i amplitude = pi total = total + InterpolatedNoise_i(x * frequency, y * frequency) * amplitude end of i loop return total end function wobei Code: [AUSKLAPPEN] total = total + InterpolatedNoise_i(x * frequency, y * frequency) * amplitude
je eine eigene funktion pro Oktave aufrufen soll. Hier ein part den ich nicht ganz verstehe: Zitat: Since all the noise functions are essentially the same, except for the values of those three big prime numbers, you can keep the same code, but simply use a different set of prime numbers for each
Der random-generator nimmt 2 werte (x/y) bzw n werte, für n dimensionen und gibt eine nummer zurück. Diese nummer wird am ende so interpoliert und berechnet, das der Perlin-noise effekt entsteht. Das erste was mir kopfzerbrechen bereitet: Da die n parameter am ende wie ein Random-seed fungieren, bräuchte ich unendlich viele Prim-zahlen um auch nur ansatzweise Zufällig generierte Noise-arrays zu erhalten. Meine bisher einzige idee um dem entgegen zu wirken, ist von anfang an einen n dimensionen-array für jede Oktave anzulegen. Diesen fülle ich mit RndFloat() oder auch mit Rnd(-1,1) - je nachdem was ich benötige. und die "Rand" funktion gibt mir am ende Array[oktave][x][y]..[n] des arrays zurück. Da die X-Y-N parameter mit x*frequenzy übergeben werden, und frequenzy immer ein exponent von 2 ist (bzw 1,2,4,8,16,...) und ich, der geschwindigkeit wegen, keine 4048x4048 array-einträge mit randomzahlen füllen will, dachte ich daran, das ich am ende vor der auswertung des parameters einfach wieder DURCH Frequenzy rechne. Das gibt aber, milde gesagt, bullshit. Oder ich habe es einfach nur falsch durchgerechnet und somit am ende den Randomeffekt ausgehebelt ![]() 2te idee wäre, mit den n parametern ein Random-seed zu errechnen und den an blitz zu übergeben. Aber auch das würde nicht ganz sauber funktionieren. Das einfachste wäre zb, RndSeed( (x shl 16) | (y) ) zu machen, was bei integerzahlen aber direkt wieder zu schwierigkeiten führt ![]() Hat jemand irgendwelche ideen, wie ich einen solchen Random-generator simulieren kann? Oder hat jemand bereits eine solche Perlin Noise funktion geschrieben und einen fix für diese Problem gefunden? :3 ----------- Bevor ich hier aber viel von der Theorie schwafel, werde ich nocheinmal von null anfangen und mir den komplettne Code übersetzen und meine idee einbringen. Ich weiß, es ist nicht gerne gesehen, wenn man nur nach hilfe fragt, ohne eigeninitiative zu zeigen ![]() Dieser folgt also etwa in einer stunde ![]() |
||
![]() |
XeresModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
Nunja, ich hab's mal probiert - das Ergebnis hat mich aber auch noch nicht wirklich überzeugt gehabt... Hier mal die 1D Version:
BlitzMax: [AUSKLAPPEN] SuperStrictIch glaube, der Zufallssamen in Noise_1D wird etwas eigenwillig behandelt, aber ich hatte bestimmt gute Gründe. Edit: Mh, ein LookUpTable... |
||
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus THERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld) |
- Zuletzt bearbeitet von Xeres am Fr, Sep 16, 2011 13:02, insgesamt einmal bearbeitet
![]() |
Midimaster |
![]() Antworten mit Zitat ![]() |
---|---|---|
stand das nicht auch in dem Artikel, auf den Noobody Dich verwiesen hat?
Die Grundlage neuer zufälliger Generierung sind zufällig ausgewählte Primzahlen: Zitat: ...Now, you'll want several different random number generators, so I suggest making several copies of the above code, but use slightly different numbers. Those big scarey looking numbers are all prime numbers, so you could just use some other prime numbers of a similar size. So, to make it easy for you to find random numbers, I have written a little program to list prime numbers for you. You can give it a start number and an end number, and it will find all the primes between the two. Source code is also included, so you can easily include it into your own programs to produce a random prime number. Primes.zip...
|
||
Gewinner des BCC #53 mit "Gitarrist vs Fussballer" http://www.midimaster.de/downl...ssball.exe |
PhillipK |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
@Midimaster: Jap, stand drin.
Die gute seite kann ich mittlerweile fast auswendig ^^ Aber die primzahlen sind das problem. Er/Sie schreibt dort munter fröhlig, das man _nur_ einen andere Primzahl gleicher länge einsetzen muss und man neue werte bekommt. Ich mein, uäh? Dieser Generator macht in meinen augen nichts weiter, wie eine Zufallszahl aus X/Y/n parametern zu bestimmen. Das gleiche kann blitz von haus aus - wenn auch etwas langsamer. Hierfür ist der RndSeed gut - der "samen" aus dem die neue zufallszahl 'wächst'. Ich glaube nicht umbedingt, das es wirklich sinnvoll ist, pro Oktave ein eigenes Primzahlen-set zusammenzustellen. 1) Hab ich gestern, trotz ausschluss verfahren (allerdings ohne Netz des Irgendwas), einen primzahlen-finder geschrieben, der zahlen zwischen start und ende auf ihre primzahligkeit überprüft und via ausschlussverfahren die rechenzeit vermindert. als er versucht hat, zwischen 1mrd und 3mrd eine neue primzahl zu finden, hab ich irgendwann nach 10minuten ohne ergebnis das programm gekillt. Primzahlen bei laufzeit finden ist also nicht - nicht ohne tausende integer im ram zu verschwenden um die suche einzugrenzen (stichwort - dieses Netz des Irgendwas zum primzahlen finden ![]() 2) Andere Noise-algorythmen verwenden ebenfalls die technik, einen array mit zufallszahlen zu füllen um eben diese zufallszahlengeneratoren zu umgehen. Das ist mit einem Simplen Seedrnd(millisecs()) relativ willkürlich (wie es sein sollte). Allerdings weiß ich nicht, wie ich den array bei mehr oktaven füllen soll - ein 3d Array( [oktave][x][y] würde es tuen, aber da ich die zufallszahlengeneratoren nicht verstehe, weiß ich nicht, ob es eine gewisse abhängigkeit zwischen der zufallszahl aus x und x*frequenzy gibt ![]() Hier mal mein jetziger versuch für einen 1d Perlin noise: BlitzMax: [AUSKLAPPEN] rem Da ich allerdings keine ahnung habe, wie ein 1D perlin noise genau aussehen könnte, weiß ich nicht, ob das nun funktioniert hat ^^ Steuerung: Links/rechts um persistence zu ändern Hoch/Runter um Octaves zu ändern Enter um einen neuen 'Coreseed' festzulegen (Coreseed= Millisecs()) ----------- @Xeres: Danke für den Code. Deins sieht tatsächlich mehr wie ein Perlin Noise aus. Meins hingegen wiederholt sich sichtlich zu oft. Ich werde mich nun dransetzen und deinen Code analysieren, vielleicht fällt mir der Springende punkt zwischen unseren beiden umsetzungen auf. Wenn ich den gefunden habe, finde ich vielleicht auch den fehler, warum meine 2d umsetzung einfach nur WhiteNoise im willkürlichen rahmen produziert hat ![]() --------- 2 Fragen hätte ich allerdings noch: Wie kann ich meine werte 'normalisieren' ? In meiner 2d umsetzung habe ich eine rot-färbung eingebaut, sobald der Höhen-wert < -1 oder > 1 ist (dh wenn er nichtmehr als 'normal' gilt ![]() 2tens - auf der seite wird geschrieben, das man 'am ende' nurnoch alle Oktaven zusammen 'blenden' muss- wie genau sieht dieses blenden aus? In meinen augen ist es diese Zeile: Code: [AUSKLAPPEN] total = total + InterpolatedNoisei(x * frequency) * amplitude
was auch bedeutet, das ich meine werte normalisieren kann, indem ich am ende Code: [AUSKLAPPEN] Return total / octaves_anzahl
zurückgebe. richtig? |
||
![]() |
Midimaster |
![]() Antworten mit Zitat ![]() |
---|---|---|
ich hab deinen Code nur so überflogen, aber festgestellt, dass die Methode NOISE() den RndSeed immer wieder auf den einmal mit MilliSecs() gefüllten CoreSeed% stellt. Das würde ja heißen, dass die genau gleiche Zufallsreihe wieder von vorne beginnt. Hast Du das bewußt so gewählt, oder liegt hier ein Denkfehler? | ||
Gewinner des BCC #53 mit "Gitarrist vs Fussballer" http://www.midimaster.de/downl...ssball.exe |
PhillipK |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
@Midimaster:
Das ist bewusst so. Später soll das Perlin Noise zeugs mal als "landschaftsgenerierung" diehnen und auch zum festlegen von Ressourcen vorkommen herhalten. Das ich immer wieder die selbe zufallsreihe nutze hat den sinn, die auswirkungen von Oktaves/Amplitude/Frequenzy zu beobachten. Durch die visualisierung und leichtem verändern fällt das gut auf ![]() Was mir immernoch zu schaffen macht, ist das man bei meiner umsetzung ziemlich eindeutig fraktale erkennen kann. Es sind wiederkehrende muster in der Höhenbildung zu erkennen. Bei xeres' umsetzung ist dem nicht so. Ich erkunde immernoch seinen code (und hab sicherheitshalber direkt mal seine Random-generierung + den seed übernommen, um den code nachzuahmen und den unterschied festzustellen.) Bis jetzt ist der einzige unterschied den ich erkennen kann, seine MinMax() funktion, die anscheinend das normalisieren (und anpassen an den screen) übernimmt :3 ------------ Ich hab grade einmal die Zufallszahlen-generatoren miteinander verglichen. Hier habe ich auf jedenfall verbesserungsbedarf, denn: (1) Mit xeres' seinem siehts schon sehr viel besser aus. (2) Spuckt xeres' seiner zahlen zwischen -1.0 und 1.0 aus, meiner hingegen spuckt werte zwischen 0.0 und 1.0 aus. Ausserdem wird in xeres' umsetzung die X koordinate durch Octaves bestimmt. Nachdem ich das mit meiner version verglichen hab, ist mir ein dicker fehler aufgefallen. Wenn man meinen kram beobachtet, und langsam "octaves" erhöht, sieht es so aus, als würde sich die linie rechts aus dem fenster rausschieben und einfach nur reinzoomen. Das bedeutet, ich muss das füllen des Höhen array überprüfen und Oktaves kann max. == Länge des arrays sein. Je höher die Octave, desto höher die frequenz, desto detailreicher ist das ganze. Wenn ich das nun richtig interpretiere, muss ich für oktave = 1 nur perlin.out[0] und perlin.out[sizeX-1]bestimmen, den rest interpolieren. für oktave=2 benötige ich.. 3 punkte? die ich bestimme und interpoliere. oder sinds schon 4? Also entweder bei 0%, 50%,100% vom output oder aber 0%, 33%, 66%, 100% - mhpf, mal schauen <.< Aber immerhin... dank des codes von Xeres' kann ich nun viel besser analysieren! dankeschön =) |
||
- Zuletzt bearbeitet von PhillipK am Fr, Sep 16, 2011 14:05, insgesamt einmal bearbeitet
![]() |
XeresModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ich habe grade noch einen relativ neuen Code gefunden: Perlin Noise Type by Bladum
Funktioniert ohne besondere Random-Funktion, aber mit einem Vorberechneten Array. Mal ausprobieren, ob ich damit was intelligenteres hin bekomme. @PhillipK: Meine Umsetzung ist sehr Fehlerhaft: Wenn du dir die Oktaven ansiehst, wirst du bemerken, das sich die Funktion nur zusammen staucht, aber keine zusätzlichen Verfeinerungen der größeren Funktion entstehen. Insofern bist du näher dran. |
||
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus THERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld) |
PhillipK |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
ugh.
Dein post kam ein wenig zu spät, ich hatte grade die vermutung angestellt, das es genau dieses zusammenstauchen ist, was mir fehlt. Dreck =) Okay, vorberechneter array ist schon ne tolle sache - so hatte ich das auch schon 2-3 x gesehen. In dem ersten wurde es als "white noise" bezeichnet - tatsächlich war dies aber nur ein Float[SizeX,SizeY]array mit werten zwischen 0.0 und 1.0, woher die noise-funktion am ende ihre Zufallszahlen erhalten hat. Allerdings weiß ich noch nicht, ob bei dem random-zahlen generator eine gewisse abhängigkeit zwischen x und x+1 besteht, oder ob das tatsächlich nur randomzahlen sind. --------------------- Soooo ![]() Ein besonderheit ist mir hier aufgefallen: Da x*frequency übergeben wird, ist der wert immer ein vielfaches von der ursprünglichen größe. Bei einem array mit N oktaven geht es natürlich nicht, das man 4086x4086 felder reserviert, auch wenn man nur ein bruchteil davon nutzt. In meinem ersten versuch mit einem solchen array hatte ich einfach am ende die aktuelle frequenz wieder dividiert. In dem Code, dessen link Xeres' gepostet hat, wird allerdings eine mod-division vorgenommen um das tatsächliche X zu erhalten. hier mal der code: BlitzMax: [AUSKLAPPEN] rem Das sieht schon sehr viel besser aus ![]() Hier habe ich allerdings die LineareInterpolation angeschaltet. Weiß immer noch nicht recht, ob Cosinus-Interpolation funktioniert, da blitzmax nicht mit dem Bogenmaß arbeitet. Ich werde nun ersteinmal eine weitere idee einbringen, die ich mal gelesen hab: ein gewisses set an Cosinus-werten für Alpha-werte (für die interpolation) bereitstellen und diese in einem array halten. Grade bei zeitkritischen noise-aufrufen, die teils ne millionen mal interpolieren, könnte das nen ziemlichen speedboost (relativ gesehen^^) geben. wenn ich das habe, gucke ich mal, wie das ganze in 2d aussieht ![]() |
||
![]() |
Noobody |
![]() Antworten mit Zitat ![]() |
---|---|---|
PhillipK hat Folgendes geschrieben: Da die n parameter am ende wie ein Random-seed fungieren, bräuchte ich unendlich viele Prim-zahlen um auch nur ansatzweise Zufällig generierte Noise-arrays zu erhalten.
Hm was? Du brauchst pro Oktave nur einen Satz Primzahlen. Im Prinzip geht es einfach darum, einen separaten Zufallsgenerator pro Oktave zu nehmen - das muss nicht unbedingt der sein, der dort im Artikel vorgeschlagen wird; man könnte ja auch den BMax-internen nehmen. So oder so, hier einmal meine Implementation von damals, als ich auf den Artikel zum ersten mal stiess, vielleicht hilft sie dir weiter BlitzMax: [AUSKLAPPEN] SuperStrict Ich verstehe nicht genau, warum du unbedingt auf einem Array mit Zufallszahlen beharrst - auf so eines greift man an sich erst zurück, wenn die Variante mit dem laufend berechnenden Zufallsgenerator funktioniert und man mit dem Zufallsgenerator Geschwindigkeitsprobleme bekommt. Dann ersetzt man den Generator durch ein 1D-Array aus vorausberechneten Zufallszahlen; je grösser es ist, desto weniger wird die Repetition sichtbar. Allerdings würde ich wirklich erst versuchen, deine Perlin-Noise-Funktion zum laufen zu bringen, bevor du Optimierungstricks anwendest. |
||
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun |
PhillipK |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Wann läuft sie denn sauber ? ![]() Ich bin zu blöd, wirklich gescheiht zu sagen, ob "DAS" nun wirklich perlin noise ist oder nur zufällig ähnlich aussieht. Leider bin ich grade durch ein wenig extra arbeit (eine PowerPoint präsentation für die Arbeit meiner Schwester^^) verhindert, deswegen kann ich grade nicht daran weiter werkeln. Zitat: Hm was? Du brauchst pro Oktave nur einen Satz Primzahlen. Im Prinzip geht es einfach darum, einen separaten Zufallsgenerator pro Oktave zu nehmen - das muss nicht unbedingt der sein, der dort im Artikel vorgeschlagen wird; man könnte ja auch den BMax-internen nehmen.
Mein einwand auf das "unendlich viele" generatoren bezog sich darauf, das ich im endeffekt maps damit gestalten, füllen und mit biomen ausstatten wollte. Ähnlich wie in minecraft (und nein, es wird kein minecraft clone, dient lediglich als erster test für perlin noise (und mal wieder zum lernen <.< ich tu fast nix anderes oO)) Da bei einem festen Primzahlensatz pro oktave immer die selben zahlen bei rumkommen, ist es im endeffekt nichts zufälliges. Ich denke sogar, ohne es zu wissen, das der Blitzmaxinterne zufallszahlen 'generator' ebenfalls eine ähnliche technik anwendet. Der aktuelle seed wird verrechnet, die werte auf min/max angepasst und ein neuer seed generiert. Beharren tue ich nicht auf den Zufallszahlen array ![]() In etwa 2-3 stunden kann ich weiter an der 2d umsetzung arbeiten, sobald ich die fertig habe, werde ich mir deinen Code zu herzen nehmen, Noobody! Danke dafür (von anderen Lernt man immernoch am besten, nicht wahr? ![]() In der zwischenzeit wäre es nett, wenn mir jemand die auswirkungen von den Oktaven und der Persistence erklären könnte .. Meine jetzige 1d umsetzung scheint, wenn ich das richtig beobachte, indirekt 'reinzuzoomen' und mehr details freizulegen, je größer die Oktave ist, die ich angebe. Persistence hingegen erhöht den unterschied den die werte aufweisen - Visualisiert nähern sich die punkte dem min/max an (-1 und 1, je nachdem was näher liegt) je höher die persistence ist. Ist das etwa das, was die werte verursachen oder habe ich hier wieder ganz klasse was falsch eingebaut und interpretiert? ![]() |
||
![]() |
Noobody |
![]() Antworten mit Zitat ![]() |
---|---|---|
PhillipK hat Folgendes geschrieben: Mein einwand auf das "unendlich viele" generatoren bezog sich darauf, das ich im endeffekt maps damit gestalten, füllen und mit biomen ausstatten wollte. Ähnlich wie in minecraft (und nein, es wird kein minecraft clone, dient lediglich als erster test für perlin noise (und mal wieder zum lernen <.< ich tu fast nix anderes oO))
Da bei einem festen Primzahlensatz pro oktave immer die selben zahlen bei rumkommen, ist es im endeffekt nichts zufälliges. Werde kreativ ![]() SuperStrict Im Prinzip muss man nur den Input-Seed des Generators ein wenig permutieren und erhält schon komplett andere Zahlenreihenfolgen, daher kann im Beispielcode auch mit Millisecs() geseedet werden und man erhält jedesmal eine andere Heightmap. PhilipK hat Folgendes geschrieben: In der zwischenzeit wäre es nett, wenn mir jemand die auswirkungen von den Oktaven und der Persistence erklären könnte ..
Meine jetzige 1d umsetzung scheint, wenn ich das richtig beobachte, indirekt 'reinzuzoomen' und mehr details freizulegen, je größer die Oktave ist, die ich angebe. Persistence hingegen erhöht den unterschied den die werte aufweisen - Visualisiert nähern sich die punkte dem min/max an (-1 und 1, je nachdem was näher liegt) je höher die persistence ist. Ist das etwa das, was die werte verursachen oder habe ich hier wieder ganz klasse was falsch eingebaut und interpretiert? ![]() Dein Code läuft da ein wenig seltsam, da er die unkonventionelle Art der ersten von dir verlinkten Seite implementiert ![]() Persistence steuert dabei, wie stark die Amplitude des Rauschens mit steigender Oktavenzahl abnimmt - die Amplitude wird ja bei steigender Oktave immer wieder mit der Persistence multipliziert. Bei hoher Persistence haben also auch Oktaven mit hoher Frequenz noch starken Einfluss auf das Ergebnis (die Kurve wird "zackig"), bei kleiner Persistence haben hohe Oktaven aber fast keinen Einfluss mehr (die Kurve wird weich). Ist aber im Prinzip alles auf der Perlin Noise-Seite erklärt (sogar mit Bildern), ansonsten kannst du in meinem Code mal mit den Argumenten für Oktavenzahl und Persistence herumspielen und schauen, was herauskommt. Sich das ganze grafisch zu veranschaulichen hilft (zumindest mir) am meisten ![]() Auf jeden Fall noch viel Erfolg bei deinem Vorhaben. |
||
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun |
PhillipK |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Ich habe nun einmal meinen PerlinNoise1D auf 2d übertragen.
Als es wieder nur ein "leicht" gesmoothter whitenoise krams wurde, hab ich mir Noobody's version durchgelesen. Das dickste was mir aufgefallen ist: Ich verwende Frequenzy anders - Code: [AUSKLAPPEN] frequency = 2^i
steht auf der seite. Noobody verwendet aber als 'grundfrequenz' 0.02 und multipliziert diese pro oktave *2 ! noobody hat aber ausserdem eine wirklich sauber funktionierende version - wie kann das sein? :O Der nächste unterschied ist die normalisierung von Noobody.. und die Prime-number-sets :3 Ach ich verstehs einfach nicht ^^ |
||
PhillipK |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Ahh ich depp =)
entschuldigt, gestern abend hatte ich keine lust mehr. Tut mir leid, das ich deinen letzten post nimmer gelesen hatte, Noobody ![]() Mit deinem Code habe ich - sogar ungefragt (*g*) eh schon rumgespielt- ich konnte den effekt einbauen den ich mir erhoffe und hab das ganze als kleines, 256frames langes, TImage rendern lassen. Mittlerweile habe ich anscheinend alle abweichungen von deinem Code zu meinem Code durchgearbeitet. Es bleibt trotzdem dabei - meins produziert no-no's und deiner go-go's :/ Ich werde mich nun dransetzen und wieder einen kompletten rewrite vornehmen. Diesmal so wie es sein soll - ohne funktion, die mir einen Array generiert, sondern nur das "gibt mir mein Perlinnoise für Koordinate XY!!" ![]() Ps: Die Art der Randomzahlen generierung ist mir schleierhaft. Es müssen angeblich umbedingt primzahlen sein, aber Noobody verwendet zb 1073741824 -> am ende ist eine 4 - dh eine Grade zahl - dh mindestens durch 2 teilbar - dh keine primzahl! Und meine erste - recht dumme aber wirksame idee - die Primzahlen zu verändern - ist folgende gewesen: BlitzMax: [AUSKLAPPEN] SeedRnd(perlin.seed) (aus meinem abklatsch kopiert, hatte getestet ob es mit deinem Random-generator besser funktioniert! aber auch in deinem code hatte ich es eingebaut - und es hat nach wie vor gute ergebnisse erzielt.) Wie kann das sein? ![]() ----------- Edit: So. Ich habe nun noobodys code analysiert und jeden schritt nachgeahmt. Und siehe da? Es funktioniert. Komischerweise bin ich der meinung, das es keinerlei änderung zu meinem 3ten Code gegeben hat (habe ich hier allerdings noch nicht gepostet) - ich werde das ganze wohl nochmal genauer analysieren müssen. Jetzt bin ich erstmal zufrieden und werde mir eine verfeinerung schreiben. Hierzu habe ich mir übelegt, eine Additionsfunktion zu schreiben. Grundgedanke ist, das es bestimmt toll aussieht, wenn man zb nur jede 2te oktave addiert (und auch berechnet) - so könnte man berge mit Kieslsteinchen ohne Hügel erzeugen - vielleicht ja ganz nützlich. Ich danke dir recht herzlich für deine gedult, noobody - du fällst mir immer wieder sehr positiv an diesem Board auf :3 |
||
![]() |
Noobody |
![]() Antworten mit Zitat ![]() |
---|---|---|
Oh, das mit der niedrigen Grundfrequenz ist eigentlich ziemlich wichtig, aber tatsächlich nirgends auf der Seite erwähnt. Im Prinzip ist es so, dass die Frequenz viel zu hoch wäre, wenn man tatsächlich 2^i nehmen würde.
Der Grund liegt darin, dass man ja mit Pixelkoordinaten arbeitet und schon bei der ersten Oktave die Frequenz 2^0 = 1 erhielte, was einer neuen zufälligen Zahl pro Pixel entspricht. Das ist natürlich nichts anderes als Ameisenrennen, darum sollte man die Frequenz verringern (in meinem Code ist es 0.01*2^i). Somit erstrecken sich bei niedrigen Oktaven die Einflussbereiche einzelner Zufallszahlen über mehrere dutzend Pixel, womit wir die gewünschten "Berge" erhalten ![]() PhillipK hat Folgendes geschrieben: Die Art der Randomzahlen generierung ist mir schleierhaft. Es müssen angeblich umbedingt primzahlen sein, aber Noobody verwendet zb 1073741824
Oh, hihi, ich sehe erst jetzt, dass ich da eigentlich einen ziemlichen Fehler im Code habe. Die ersten drei Zahlen im Primzahl-Array müssen tatsächlich Primzahlen sein, aber die letzte sollte eigentlich immer 2^30 sein (1073741824). Der Grund dafür ist, dass, nachdem die Zufallszahl als Integer ausgerechnet wird, noch mit $7FFFFFFF geANDet wird. Damit liegt die Integer-Zufallszahl zwischen 0 und 2^31. Wenn man dann mit 2^30 dividiert, erhält man eine zufällige Fliesskommazahl zwischen 0 und 2.0 - wenn man die dann von 1.0 subtrahiert, erhält man die gewünschte Zufallszahl zwischen -1.0 und 1.0. Ich habe das wohl damals falsch unterpretiert und die 1073741824 ebenfalls als frei wählbare Primzahl aufgefasst (obwohl sie ja nicht mal eine ist). Der Generator funktioniert grundsätzlich immer noch, wenn man die anderen Zahlen nicht-prim wählt (d.h. es werden immer noch wild durcheinandergewürfelte Zahlen generiert), allerdings verringert sich die Periodenlänge um einiges, wenn man nicht-prime Zahlen wählt. |
||
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun |
PhillipK |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Wieder eine wichtige auskunft! Je größer frequenz desto weniger pixel werden überspannt!
Ziemlich wichtig zu wissen, wenn man (wie ich) einen gewissen einfluss auf die erscheinung der Berge haben möchte. Ich bin beeindruckt, du kannst die rechnung hinter der Primzahlen-verwürfelung sogar verstehen? Nun, wenn das auchnoch ein fehler ist, gibt das nacher beim normalisieren fehler und ich habe teilweise schwebende blöcke. Das kommt auf meine Todoliste zum abändern des Codes ![]() Mich wurmts ziemlich, das mein code nun fast wie eine Kopie wie deiner aussieht, aber nunja. Ich glaube, eine wesentlich andere implementierung wird es wohl nicht geben. Ich habe es mir noch zum ziel gesetzt, das ganze so schnell wie möglich zu machen. Meine ideen hierzu sind: -Aufrufe von Funktionen/methoden verringern - dh eine 2te Version anfertigen wo alles in ein-zwei riesenfunktionen aufgeteilt wird. -Bei Cosinus-interpolierung bleiben, allerdings einen array vorfertigen, welcher NOISE_SIZE einträge enthält - statt (alpha * 180) aufzurufen, kommt einfach CosinusArray[alpha*180] dran - rein logisch betrachtet, sollte das hinhauen^^ -Rausfinden, wie ich die maximal sichtbare anzahl der oktaven anhand von NOISE_SIZE berechnen kann und diese max-zahl nicht überschreiten, auch wenn Octaves was größeres angibt. -Generell variablen vermeiden und direkt die rechnugnen zusammentragen (megalangezahlen, ich komme) Wenn alles klappt, kann ich den speed sicher noch drücken ![]() Ihr dürft gespannt sein =) |
||
PhillipK |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Eine weitere Zwischenfrage.
Um fix wieder ein Erfolgserlebnis zu haben, hab ich angefangen, den Perlin-code in mein Projekt einzupflegen. Ich konnte hieraus erfolgreich eine map anzeigen. Um zu testen, habe ich ersteinmal die höhe auf 16 beschränkt - hierzu habe ich die farben auf eben diese 16 höhenstufen gebrochen. (Nach dem wrappen auf einen wert von 0 bis 1 (float) : ) Arr[x,y] = Byte(Arr[x,y] * hoehenstufen:int) / Float(hoehenstufen) Daraus kommen dann (visualisiert) solche bilder: ![]() Ist es irgendwie möglich, anhand der parameter (und evtl der Frequenzänderung pro Oktave) den Kontrast zu verändern? Ich hätte gerne größere Täler, aber dafür Steilere Berge- sprich das was nun dunkel grau ist soll "mehr" werden, dafür aber stark abfallend weiß->hellgrau->grau für die Berge. meine idee hierzu wäre, rauszufinden, welche Oktave eben diese weißen "berge" berechnet und diese evtl doppelt zu blenden. Nachteil wäre aber, das damit wahrscheinlich einfach nur die 'helligkeit' des gesamten bildes angehoben würde ![]() Also vermute ich, das es sehr wohl machbar ist, aber wahrscheinlich eher beim Interpolieren? ![]() EDIT: Image-link ausgebessert. Ich idiot hab die Galerie-regeln missachtet ![]() Gleichzeitig ist dies wieder eine weitere Version meiner aktuellen fortschritte. Das problem ist allerdings immernochnicht behoben. |
||
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group