Raycaster und Prozessoptimierung
Übersicht

![]() |
SkabusBetreff: Raycaster und Prozessoptimierung |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hallo!
Ich habe mich, angeregt durch Noobody, einige Zeit mit einem Raycaster beschäftigt, da ich in der Uni gerade ähnliche Themen habe und ich schon seit geraumer Zeit eine Idee für ein Spielremake im Kopf habe, habe ich mich an die Aufgabe gesetzt einen Raycaster zu schreiben. Bissher bin ich bereits recht zufrieden mit meinen Ergebnissen, habe allerdings momentan ein Problem, an dem ich mir(inklusive mehreren Info-Studenten und nem Mathestudent) die Zähne ausbeiße... Zunächst einmal könnt ihr die Release-Version hier laden: https://www.blitzforum.de/upload/file.php?id=7535 Und hier noch ein unspektakulärer Screenie: Leider ist das Ganze extrem langsam, da ich eine höchst unoptimierte Art implementiert habe den Strahl zu konstruieren. Ich nutze die einfache Beziehung zum Polarkoodinatensystem, dass eine Linie des Winkels a mit dem sin a und dem cos a Steigungsdreiecke bildet. Das resultierende Problem ist allerdings, dass ich dann für jedes zu betrachtende Feld auf meiner 2D-Karte jeden einzelnen Punkt auf dem Feld überprüfe.Bei einer Feldgröße von 64*64 Einheiten würde er im besten Fall 64 Punkte prüfen, im Falle von Genauigkeitskorrekturen sogar noch mehr. Was allerdings nicht notwendig ist, wie ich in diversen Quellen gelesen habe. Überall, sei es in meinem Raycasting-Buch, vertex Raycaster-Code, oder sonstigen Internettutrorials steht überall dass ich die Beziehung des tangens nutzen kann um meinen Code zu optimieren. Leider habe ich in den letzten Wochen selbst mit Hilfe mehrerer Studenten keine Lösung gefunden, warum mein aktueller Code mir nur Quark ausgibt.Wie mein aktuelles Ergebnis aussieht seht ihr hier: Mein Code sieht so aus: Hier die Funktion die die Höheninformationen für den Rendering-Prozess ermittelt: BlitzMax: [AUSKLAPPEN]
Und hier jetzt die "optimierte" Unterfunktion, die den Fehler verurrsacht: BlitzMax: [AUSKLAPPEN]
Problem ist jetzt wie gesagt, das die Höheninformationen falsch in den sceneRows-Array geschrieben werden, ja manchmal sogar nicht gefunden wurden, obwohl die "Kamera" in einem vollständig abgeschlossenen Raum steht. Wir haben bereits mehrmals alle mathematischen Grundlagen durchgerechnet und kommen einfach nicht drauf,wo da der Fehler liegt.Ich hab auch bereits Noobodys und vertex' Code gewälzt und mir nen Wolf probiert, aber ich bekomme die absurdesten Farben und Formen raus, egal was ich probiere. Der Fehler liegt warscheinlich an der Stelle wo deltaX und deltaY berechnet werden. Allerdings habe ich auch hier: http://www.permadi.com/tutorial/raycast/rayc7.html , die selbe Formel gefunden, welche auch vollständig Sinn macht.Das Ergebnis sieht aber wie gesagt aus wie...naja ihr seht es ja... Meine Frage also, weiß jemand was ich falsch mache? Weiß jemand ob ich einen grundsätzlichen Denkfehler habe, oder nur im speziellen irgendwas falsch mache? Ich hoffe jemand von euch kann mir sagen was nicht funktioniert. Wäre ich euch wirklich sehr dankbar... Danke im Vorraus! MfG Ska - |
||
"In einer so verrückten Welt, kann man um in ihr zu überleben nur eines tun, nämlich eben jenes werden: Ein Verrückter!" -Selbstzitat
aktuelles Projekt: Aves Certim - Der Galgen ist nicht weit! Ein SNES-RPG mit Handels- und Wirtschaftselemente. Infos?Hier: http://www.blitzforum.de/worklogs/234/ Besucht meine Seite: www.seelenfriedhof.de.vu |
![]() |
Casiopaya |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hi!
mangels Zeit habe ich nun deinen Code nicht durchlesen können, aber aus meiner Erfahrung aus meinem VG Raytracer (kannst ja mal danach suchen): Zum Performance-Problem: Also, in einer unoptimierten Version schneidest du alle Objekte mit dem Strahl und berechnest jeweils den Schnittpunkt. Das sollte auch bei 100ten Wänden sehr schnell gehen. Bei noch mehr musst du ne Beschleunigungsstruktur einbauen. Durch den Schnittpunkt hast du gleichzeitig die Entfernung zum Objekt, das sichtbare Objekt ist das, mit der geringsten Entfernung, was uns zu 2. führt: >> Hier die Funktion die die Höheninformationen für den Rendering-Prozess ermittelt: Ich weis nun nicht genau was du mit "Höheninformationen " meinst, aber beim Raycasten hängt die Höhe einzig und alleine von der Entfernung ab. Da du die Entfernung zur Sichtbarkeitsberechnung ohnehin brauchst muss hier gar nichts mehr berechnet werden. Also zusammengefasst: - Du hast ein 2D-System, das mathematisch beschrieben wird. - Du hast einen Kamerapunkt, (x1,y1) - Pro Bildspalte hast du einen Sichtstrahl, die "Brennweite" deines Kameraobjektivs ergibt sich aus den Winkelgrenzen links und rechts. Nehmen wir an wenn du genau nach vorn schaust ist der Sichtstrahl um 0 Grad gekippt, dies wäre der Sichtstrahl für die Bildspalte in der Bildschirmmitte. Links ist der Strahl um vlt. -30 Grad gedreht, an der rechten Seite um +30Grad. Der Sichtstrahl selbst ist nichts anderes als eine (Halb-) Gerade in 2D, also ein (x1,y1) + lamda(x2,y2) - Deine Wände sind ebenfalls Geraden, pro Bildzeile musst du die Sichtgerade mit allen geraden schneiden, den Schnittpunkt (g1,g2) berechnen, dessen Abstand zur Kamera (x1,y1), und dann enstprechend der Entfernung eine Linie zeichen. Grüße |
||
![]() |
Skabus |
![]() Antworten mit Zitat ![]() |
---|---|---|
Vielen Dank erstmal...
Das Raycasting-Prinzip habe ich, hoffentlich, soweit verstanden. Mit "Höheninformationen" meine ich die korrespondierende Höhe zur jeweiligen Entfernung.Ich berechne ja schließlich für jeden Sehstrahl diejenige Entfernung die zwischen Kameraposition und der ersten "anzutreffenden" Wandspalte besteht. Entsprechend der errechneten Entfernung kann ich die Höhe meiner Wand an der entsprechenden Bildspalte berechnen. Nutze ich dabei die Beziehung: aktuelleXPosition + cos Strahlenwinkel aktuelleYPosition + sin Strahlenwinkel Dabei gehe ich also davon aus, dass das Steigungsdreick das der Strahl mit dem Winkel a eine Hypotenuse von der Länge 1, die Ankatete von 1*(cos a) und die Gegenkatete von 1*(sin a) hat. Was passiert nun wenn ich zur aktuellen Position deltaX und deltaY dazu addiere: Ich kann jeden Punkt auf dem Strahl erreichen.Das brauche ich aber gar nicht.Denn wenn ich einmal einen Punkt der innerhalb eines Feldes in meiner 2D-Karte als "keine Wand" gekennzeichnet habe, so benötige ich nicht noch den nächste und übernächsten Punkt dieses Feldes. Und zur Lösung dieses Problem habe ich ja die beiden findDisDiagH und findDisDiagV geschrieben.Damit ich nur die Schnittpunkte der Felder benötige und zwar die horizontalen Schnittpunkte und die vertikalen Schnittpunkte. Darum, und so finde ich es überall, dachte ich mir: deltaX = GRID_SIZE (in meinem Fall 64 Einheiten) und deltaY = dX / tangens(Blickwinkel) Ich gehe ja davon aus, dass der Tangens des Blickwinkel im Polarkoordinatensystem die Hypotenuse des Steigungsdreiecks ist und ich somit die Einheiten die ich in Y-Richtung dazuaddieren muss dadurch rausbekomme dass ich die Ankatete durch die Hypotenuse teile und so die Gegenkatete rausbekomme. Nun müsste ja "eigentlich" der Prozess nicht nur korrekt sondern sogar um ein vielfaches schneller sein. Aber stattdessen bekomme ich halt abstrakte Formen raus und weiß eben nicht warum...^^" MfG Ska |
||
"In einer so verrückten Welt, kann man um in ihr zu überleben nur eines tun, nämlich eben jenes werden: Ein Verrückter!" -Selbstzitat
aktuelles Projekt: Aves Certim - Der Galgen ist nicht weit! Ein SNES-RPG mit Handels- und Wirtschaftselemente. Infos?Hier: http://www.blitzforum.de/worklogs/234/ Besucht meine Seite: www.seelenfriedhof.de.vu |
![]() |
Casiopaya |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hi
Skabus hat Folgendes geschrieben: Nutze ich dabei die Beziehung: aktuelleXPosition + cos Strahlenwinkel aktuelleYPosition + sin Strahlenwinkel hmm, sorry aber ich muss zugeben, dass ich das nicht verstehe. Die Höhe der Wand hängt doch ausschließlich von der Entfernung ab, völlig unabhängig davon in welchem winkel du die Wand mit dem Sichtstrahl schneidest. Da alle Wände in der "Realität" gleich hoch sind, ist jedes Wandsegment (horizontal), das eine Entfernung A von der Kamera entfernt ist, genau gleich hoch. Wie das Verhältnis zwischen Abstand und Höhe nun ist, kannst du selbst festlegen. Da gibt es nichts korrektes oder inkorrektes, da je nach Verhältnis einfach eine andere Kamerabrennweite angenommen werden kann. Zunächst kannst du ja z.B. annehmen, dass alle Dinge, die 1 Meter entfernt sind 50% der Bildschirmgröße haben, alle die 2 entfernt sind 25 % etc (nur ein Vorschlag, hier kommt es darauf an, welches Einheitensystem du verwendest). Könntst du mal ganz kurz und knapp in Worten erklären, was dein Algor. genau macht? (ICh hab das Posting schon komplett durchgelesen ![]() |
||
- Zuletzt bearbeitet von Casiopaya am Mi, Dez 02, 2009 18:00, insgesamt einmal bearbeitet
![]() |
Skabus |
![]() Antworten mit Zitat ![]() |
---|---|---|
Nein die Beziehung
aktuelleXPosition + cos Strahlenwinkel aktuelleYPosition + sin Strahlenwinkel benutze ich nicht zur Berechnung der Höhe, sondern zur Konstruktion meines Sehstrahls.Ich muss doch in Abhängikeit des Winkels des aktuellen Strahls einen imaginären Sehstrahl zwischen Kameraposition und der nächsten Wand berechnen. Die Höhenverhältnisse sind wie du ja sagst vollkommen egal. Da teile ich einfach irgendeinen Wert durch die Entfernung, damit es passt. Mein Problem liegt wie gesagt bei der Konstruktion der Strahlen und die ist, bei Nutzung von sin a cos a extrem langsam, da ich wie gesagt jedesmal nur sin a und cos a zur aktuellen Position hinzuaddiere(bzw. subtrahiere)... Ich hoffe das es jetzt etwas klarer gewordne ist^^ MfG Ska |
||
"In einer so verrückten Welt, kann man um in ihr zu überleben nur eines tun, nämlich eben jenes werden: Ein Verrückter!" -Selbstzitat
aktuelles Projekt: Aves Certim - Der Galgen ist nicht weit! Ein SNES-RPG mit Handels- und Wirtschaftselemente. Infos?Hier: http://www.blitzforum.de/worklogs/234/ Besucht meine Seite: www.seelenfriedhof.de.vu |
![]() |
Casiopaya |
![]() Antworten mit Zitat ![]() |
---|---|---|
Skabus hat Folgendes geschrieben: Mein Problem liegt wie gesagt bei der Konstruktion der Strahlen und die ist, bei Nutzung von sin a cos a extrem langsam, da ich wie gesagt jedesmal nur sin a und cos a zur aktuellen Position hinzuaddiere(bzw. subtrahiere)... auch auf die Gefahr hin dass ich dich nun wieder falsch verstanden habe, aber den Sichtstrahl selbst kannst du auch ganz ohne Sin und Cos berechnen, einfach indem du eine "Projektstionslinie" vor die Kamera "stellst". Diese Linie liegt horizontal auf Kamerahöhe und hat eine linke und eine rechte ecke. Du fängst mit der linken Ecke an (Ex,Ey), nun hast du 2 Punkte (die Kamera Cx,Cy und (Ex,Ey), daraus kannst du dir deine Gerade in Form a * yb bauen. Für die nächste Bildspalte zählst du ein ExDiff und EyDiff auf Ex bzw Ey drauf, sodass du nach genau 1000 Schritten (falls die Auflösung eine Breite von 1000 Pixel hat) am andere Ende der Linie angelangt bist. Du läufst die Linie also entlang, baust dir jedesmal den Sichtstrahl aus 2 Punkten (Feste Kamera und wandernder Punkt) ganz ohne Trigonometrie. (Beim Bewegen musst du nur die beiden Eckpunkte der Linie bewegen) Aber mal anders: Mehrere 1000 Sinusse oder Cosinusse pro Sekunde sollten dich performancemäßig kein Problem sein? EDIT: Etwas missverständlich ist hier vlt das Ex und Ey: Das ist so gemeint, dass du von oben auf die Szenerie schaust, dann hat die Kamera eine xy Position, und jeder Punkt der Linie ebenfalls. |
||
![]() |
Skabus |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hm, du hast mich schon richtig verstanden.
Das Problem ist nur, dass ich das eben nicht ohne Berücksichtigung des Blickwinkels machen kann. Mein Field of View habe ich mit 64 festgelegt.Vom aktuellen Blickwinkel der Kamera will ich die Hälfte davon subtrahieren und die Hälfte addieren. Angenommen mein Blickwinkel ist 0° so geht meine Abtastreichweite von -32° und +32° Was bedeutet 328° bis 32°.Da ich eine Auflösung von 640*480 habe muss ich den FOV / 640 teilen.Denn ich brauche jeweils 0.2 * 640 um jede Bildschirmspalte zu erreichen. Das System basiert meiner Ansicht nach auf der Nutzung dieser Angaben. Ich versteh nicht wirklich warum ich das jetzt ohne Trigonometrie und Winkel machen soll^^" Hast du dir meinen Code mal angesehen? MfG Ska |
||
"In einer so verrückten Welt, kann man um in ihr zu überleben nur eines tun, nämlich eben jenes werden: Ein Verrückter!" -Selbstzitat
aktuelles Projekt: Aves Certim - Der Galgen ist nicht weit! Ein SNES-RPG mit Handels- und Wirtschaftselemente. Infos?Hier: http://www.blitzforum.de/worklogs/234/ Besucht meine Seite: www.seelenfriedhof.de.vu |
![]() |
Noobody |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ich habe mir deinen Code mal durchgesehen und ich denke, ich sehe das Problem. Da du schon auf diese Seite hier verlinkt hast, würde ich empfehlen, sie nochmals durchzulesen ![]() In deinem Code prüfst du nur auf Schnittpunkte mit horizontalen Wänden. Damit du ein korrektes Resultat erhältst, musst du aber sowohl horizontale wie auch vertikale Schnittpunkte berechnen und zum Schluss die Wand zeichnen, deren Schnittpunkt näher an der Kamera liegt. Prüfst du nur auf eine Sorte von Schnittpunkten, so erscheinen die Wände je nach Blickwinkel solide, zerstückelt oder ganz durchlässig. Allerdings kommt mir der Algorithmus ein wenig ineffizient vor, wie er auf der Seite vorgeschlagen wird; ich schätze, ein DDA-Algorithmus wäre um einiges schneller, da vertikale und horizontale Schnittpunke gleichzeitig und nicht nacheinander errechnet werden. Falls ich Zeit finde, probiere ich mal aus, was schneller ist. |
||
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 |
![]() |
Skabus |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hey Noobody,
danke das du dir die zeit nimmst ![]() Ich hab nur zur Übersicht die vertikale Berechnung weggelassen, im Orginalcode ist die vertikale Berechnung mit enthalten. Ich prüfe im Anschluss beider Funktionsaufrufe ob die Distanz der vertikalen Berehcnung kleiner als die der horizonatlen Berechnung ist. Leider ist kein Unterschied zu erkennen, das Ergebnis sieht letzlich genauso aus ![]() Ich bin mir sicher, dass irgendwas an meinem Algorithmus nicht stimmt.... Ich kann gerne den gesamten Code nochmal hochladen, aber ich hab da massenweise Testcode und überflüssige Funktionen drin und wollte niemanden verwirren... Wäre wirklich nett wenn du mir da helfen könntest^^" MfG Ska Wie genau funktioniert ein DDA-Algorithmus?Kann ich mich dazu irgendwo belesen?Hab diesbezüglich bissher nix gefunden... |
||
"In einer so verrückten Welt, kann man um in ihr zu überleben nur eines tun, nämlich eben jenes werden: Ein Verrückter!" -Selbstzitat
aktuelles Projekt: Aves Certim - Der Galgen ist nicht weit! Ein SNES-RPG mit Handels- und Wirtschaftselemente. Infos?Hier: http://www.blitzforum.de/worklogs/234/ Besucht meine Seite: www.seelenfriedhof.de.vu |
![]() |
Noobody |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ich habe das mal mit einem DDA-Algorithmus umgesetzt und das Programm läuft wie erwartet vergleichsweise schnell BlitzMax: [AUSKLAPPEN] SuperStrict Die Beschreibung des Algos an sich findest du in diesem Artikel. Den brauchte ich mal für ein Raytracer-Projekt ![]() |
||
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 |
![]() |
Skabus |
![]() Antworten mit Zitat ![]() |
---|---|---|
Vielen Dank Noobody für deine Mühe ![]() ich hab mich jetzt eine ganze Weile mit diesen Thema(vor allem DDA) beschäftigt, allerdings scheint auch diese Methode auf schwachen PC´s nicht optimal genug zu sein...Leider... Auf meinem eePC mit 800 Mhz läuft es gerade mal mit 5 FPS(maximal), was für ein vernünftiges Spiel viel zu wenig ist.Gibt es Mittel und Wege das Ganze mit BMax noch zu optimieren? Ich versuch gerade, einen Raycaster mit DDA-Algorithmus mit C++ und ner Grafikbibilothek zu realisieren, hab da aktuell aber noch arge Verständnisprobleme, allerdings siehts da bissher auch nicht sonderlich rosig aus... Ein Bekannter hat mir empfohlen die zeitkritischen Passagen mit Assembler zu realisieren, hab allerdings noch nicht ausprobiert in wie weit das funktionieren würde. Wäre schön wenn du, bzw. auch gerne jeder andere, mir da noch nen Tip geben könntest, wie ich da noch mehr Geschwindigkeit rausholen kann... Mein Dank sei dir gewiss ![]() MfG Ska |
||
"In einer so verrückten Welt, kann man um in ihr zu überleben nur eines tun, nämlich eben jenes werden: Ein Verrückter!" -Selbstzitat
aktuelles Projekt: Aves Certim - Der Galgen ist nicht weit! Ein SNES-RPG mit Handels- und Wirtschaftselemente. Infos?Hier: http://www.blitzforum.de/worklogs/234/ Besucht meine Seite: www.seelenfriedhof.de.vu |
![]() |
Noobody |
![]() Antworten mit Zitat ![]() |
---|---|---|
Der Bottleneck liegt hier aber nicht beim DDA bzw. Raycasting-Algo - bei Messungen hier verbraucht der Algo gerade mal 0-4ms, je nach Position auf der Karte.
Der wahre Übeltäter ist die Pixmap, die bei mir immer so um die 15ms zum Zeichnen benötigt. Das liegt daran, dass das 3D-Fenster, das durch Max2D geöffnet wird, einfach nicht auf Pixelmanipulation ausgelegt ist und DrawPixmap daher sehr, sehr langsam ist. Es steht ja auch bei der Doku des Befehls bei: "This function is intended for debugging purposes only - performance is unlikely to be stellar." Die einzige Möglichkeit ist nun, dir eine andere Grafiklib zu schnappen (z.B. SDL), die direkte Buffermanipulation erlaubt oder aber die Fenstererstellung selber vorzunehmen. |
||
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 |
![]() |
Skabus |
![]() Antworten mit Zitat ![]() |
---|---|---|
Aso, na wunderbar, dann werd ich mich mal daran machen, mit der SDL oder irgendeiner anderen geeigneten Lib
die Sache mal umzusetzen. Vielen Dank erstmal^^ MfG Ska |
||
"In einer so verrückten Welt, kann man um in ihr zu überleben nur eines tun, nämlich eben jenes werden: Ein Verrückter!" -Selbstzitat
aktuelles Projekt: Aves Certim - Der Galgen ist nicht weit! Ein SNES-RPG mit Handels- und Wirtschaftselemente. Infos?Hier: http://www.blitzforum.de/worklogs/234/ Besucht meine Seite: www.seelenfriedhof.de.vu |
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group