Fließkommazahlen waren für große Welten immer problematisch.
Dieser Artikel erklärt die Hintergründe und bietet die offensichtliche Alternative - Festkommazahlen. Einige Fakten sind wirklich beeindruckend, wie:
"64 Bit Präzision bringen Sie mit Submikrometer-Präzision zur weitesten Entfernung von Pluto von der Sonne (7,4 Milliarden km)."
Nun, die Präzision im Submikrometerbereich ist mehr als alle FPS-Anforderungen (für Positionen und sogar Geschwindigkeiten) und es würde Ihnen ermöglichen, wirklich große Welten zu bauen.
Meine Frage ist, warum wir immer noch Fließkomma verwenden, wenn Festkomma solche Vorteile hat. Die meisten Rendering-APIs und Physikbibliotheken verwenden Gleitkommazahlen (und weisen Nachteile auf, sodass Entwickler diese umgehen müssen).
Sind sie so viel langsamer?
Wie gehen skalierbare Planetenmotoren wie Outerra oder Infinity mit dem großen Maßstab um? Verwenden sie feste Punkte für Positionen oder haben sie einen Algorithmus zur Raumteilung?
Antworten:
Wenn Sie mir einen schamlosen Stecker erlauben, gebe ich Ihnen ein Beispiel von einem echten Spiel, an dem ich arbeite (YouTube-Videolink).
Das Spiel hat eine unendliche, prozedural erzeugte Welt auf einer Physik-Engine. Es verwendet Gleitkommazahlen mit einfacher Genauigkeit. Nach ein paar hundert Metern Spielraum beginnen Präzisionsprobleme aufzutreten (und werden immer schlimmer, je weiter Sie vom Ursprung entfernt sind).
Meine Lösung? Etwa alle 200 m bewege ich die ganze Welt um 200 m in Richtung des Ursprungs zurück (wenn Sie einen der Prototypen auf meiner Site suchen und ausprobieren und das [w] orld-Debug-Overlay aufrufen möchten, können Sie dies beobachten).
Warum nicht Fixpunkt verwenden? Oder doppelte Präzision? Statt einfacher Präzision? Weil alles andere Gleitkommazahlen mit einfacher Genauigkeit verwendet!
Die von mir verwendete Physik-Engine verwendet sie, XNA verwendet sie, und die Daten, die auf die Grafikkarte geladen werden, werden als Gleitkommazahlen mit einfacher Genauigkeit formatiert. Sogar die Sprache selbst ist darauf ausgelegt, mit Gleitkommazahlen zu arbeiten - Schreiben und (was noch wichtiger ist) Lesen
0.5f
ist viel einfacher als0x80000000L
.Es geht einfach darum, was in der Praxis einfacher ist. Und der klare Gewinner ist sich der Probleme mit der Fließkommapräzision bewusst und schreibt ziemlich einfache Funktionen zum Zurücksetzen der Welt auf Null (oder zum Implementieren einer Raumaufteilung oder was auch immer für Ihr Spiel geeignet ist).
Und schließlich noch ein Beispiel - Orbiter ist ein Spiel (Simulation, wirklich), bei dem es wirklich um Präzision geht. Nicht nur im Raum, sondern auch in der Zeit (Zeitbeschleunigung plus umlaufende Körper - ich möchte nicht, dass sie jetzt vom Himmel fallen). Es verwendet auch Gleitkommazahlen und verwendet einen Hack , um die Stabilität aufrechtzuerhalten.
quelle
Erstens - ja, sie sind bedeutend schneller. Selbst wenn Sie Festkomma so schnell wie eine "normale" FPU zum Laufen bringen können, verfügt ein echter Gleitkomma über vorteilhafte Anweisungen wie fsel, um die Verzweigung zu beenden, oder SIMD, um auf vielen Gleitkommas gleichzeitig zu arbeiten. GPUs verwenden auch Gleitkommazahlen, zumindest in ihren Benutzeroberflächen.
Zweitens erreichen Sie mit 64 Bit auch einen ziemlich hohen Fließkommawert - die meisten Leute verwenden immer noch 32, aber der Hauptvorteil ist, dass es skaliert. Diese Festpunktskala hat eine feste Genauigkeit. Egal, ob Sie die Sonne nach Pluto messen oder auf der anderen Straßenseite, Sie erhalten die gleiche Präzision. Gleitkommawerte liefern viel genauere Ergebnisse, wenn alle beteiligten Werte kleiner sind. Da von generischen Physikbibliotheken erwartet wird, dass sie mit vielen Spielen in verschiedenen Maßstäben zumindest passabel funktionieren - und einige Spiele selbst möglicherweise sehr unterschiedliche Maßstäbe haben -, müssen sie eine Art Zahl verwenden, die in vielen Maßstäben funktioniert.
quelle
Ein weiterer wichtiger Punkt ist, dass Schwimmer nicht so ungenau sind, wie die Leute hier zu denken scheinen. Ein 32-Bit-Float verfügt über 24 Bit mit vollständiger Ganzzahlgenauigkeit. Dies bedeutet, dass es für einen bestimmten Bereich mindestens so genau wie ein 24-Bit-Festpunktwert ist. Während Floats mit zunehmendem Wert ungenauer werden, läuft ein fester Punktwert einfach über und dreht sich irgendwann um. Eine Verringerung der Genauigkeit ist ein besserer Rückfall. Schwimmer können auch überlaufen, aber weit, weit später. Ich würde gerne Ihre Gesichter sehen, wenn sich Ihre Welt aufgrund eines Überlaufs an festen Punkten plötzlich auf -2 ^ 31 dreht.
64-Bit-Gleitkommawerte haben eine Ganzzahlgenauigkeit von 53 Bit und sind daher sehr genau.
quelle
In einem FPS-Kontext können Festpunktwerte tatsächlich eine Verbindlichkeit sein. Gleitkommazahl nahe Null ist genauer. Es wird nur über große Entfernungen der Fixpunkt vorgezogen. Die Antwort ist einfach, dass es vom Kontext abhängt.
In so etwas wie einer Galaxie können Sie Referenzrahmen verwenden. Verwenden Sie eine große Skala für die Sonnensysteme und verwenden Sie dann den Sonnenmittelpunkt (oder einen ähnlichen Punkt) als Ursprungspunkt für alles innerhalb des Systems. Mit diesem System können Sie Ihren Kuchen haben und ihn sozusagen essen, und es ist nicht schwer, ihn sich vorzustellen.
IIRC, der Entwickler von Infinity, gab an, dass er in einem seiner Interviews ständig Skalenprobleme durchgearbeitet habe.
quelle
Wenn du es noch nicht getan hast, solltest du das Planet Rendering Tutorial auf GameDev.net definitiv ausprobieren. Was die Raumteilung betrifft, besteht eine Lösung darin, zwei separate Positionsvariablen beizubehalten - eine Makroskala und eine Mikroskala. Das funktioniert ganz gut (getestet).
Die genaue Lösung hängt davon ab, wie Sie mit extremen Entfernungen im Motor umgehen möchten. Planen Sie Sprungtore oder Zeitkomprimierung?
quelle
Einer der Gründe ist, dass Gleitkomma-Arithmetik "gut genug" ist (oder zumindest war), und ziemlich genaue Ergebnisse schnell liefert.
Solange Sie die Einschränkungen der Gleitkomma-Arithmetik kennen und Ihre Algorithmen entsprechend anpassen (siehe Andrew Russells Antwort), werden Sie Code produzieren, der "funktioniert".
quelle
Ich schreibe ein Spiel. In meinem Spiel / Programm zeichne ich ein Raumschiff am Ursprung mit einer ziemlich festen Kamera und meinen Planeten zeichne ich mit einer separaten Kamera. Und diese beiden Dinge erledigen das Problem für mich, aber mein Planet ist noch nicht sehr detailliert. Was die Lösung angeht, die Andrew Russell über das Bewegen der Welt erwähnt hat (und ich gehe davon aus, dass die Kamera und ihre Bewohner zum Ursprung zurückkehren), würde ich das wirklich nicht versuchen, wenn Sie jemals vorhaben, das Spiel zu einem vernetzten Spiel zu machen. Wenn Sie die Welt auf der Serveranwendung basierend auf den Bewegungen der einzelnen Clients verschieben würden, würde die Welt am Ende um eine Position kämpfen. Und würde seine Position die ganze Zeit von allen Spielern einnehmen, was eine große Panne wäre.
quelle