La virgule flottante a toujours été gênante pour la précision sur les grands mondes.
Cet article explique les coulisses et offre l’alternative évidente: les nombres à points fixes. Certains faits sont vraiment impressionnants, comme:
"Bien 64 bits de précision vous permettent d'atteindre la distance la plus éloignée entre Pluton et le Soleil (7,4 milliards de km) avec une précision inférieure au micromètre."
Une précision inférieure au micromètre est plus importante que tout besoin en ips (pour les positions et même les vitesses), et vous permettrait de construire de très grands mondes.
Ma question est la suivante: pourquoi utilisons-nous toujours la virgule flottante si le point fixe présente de tels avantages? La plupart des API de rendu et des bibliothèques de physique utilisent une virgule flottante (et souffrent de ses inconvénients, les développeurs doivent donc les contourner).
Sont-ils tellement plus lents?
De plus, comment pensez-vous que les moteurs planétaires évolutifs tels que outerra ou l'infini gèrent la grande échelle? Utilisent-ils un point fixe pour les positions ou ont-ils un algorithme de division d'espace?
Réponses:
Si vous me permettez une fiche éhontée, je vais vous donner un exemple tiré d'un vrai jeu sur lequel je travaille (lien vidéo YouTube).
Le jeu propose un monde infini, généré de manière procédurale, sur un moteur physique. Il utilise une virgule flottante simple précision. Après quelques centaines de mètres d’espace de jeu, des problèmes de précision commencent à se poser (et s’aggravent de plus en plus par rapport à l’origine).
Ma solution? Tous les 200 m environ, je ramène le monde entier de 200 m vers l'origine (si vous souhaitez trouver et essayer l'un des prototypes sur mon site et afficher le calque de débogage [mondial], vous verrez que cela se produit).
Pourquoi ne pas utiliser un point fixe? Ou double précision? Au lieu de la simple précision? Car tout le reste utilise une virgule flottante simple précision!
Le moteur physique que j'utilise l'utilise, XNA l'utilise, les données chargées sur la carte graphique sont formatées en virgule flottante simple précision. Même le langage lui - même est conçu pour fonctionner avec des nombres à virgule flottante - écrire et (plus important encore) lire
0.5f
est beaucoup plus facile que0x80000000L
.C'est simplement une question de facilité en pratique. Et le gagnant est clairement conscient des problèmes de précision en virgule flottante et de l’ écriture. relativement simples, «déplacer le monde à zéro» (ou mettre en œuvre le partitionnement d’espace ou ce qui convient à votre jeu).
Et enfin un autre exemple - Orbiter est un jeu (de simulation, vraiment) qui a vraiment besoin de se soucier de la précision. Pas seulement dans l'espace mais aussi dans le temps (accélération du temps et corps en orbite - ne voulez pas qu'ils tombent du ciel, maintenant). Il utilise également des nombres à virgule flottante et utilise un hack pour maintenir la stabilité.
la source
Premièrement - oui, ils sont beaucoup plus rapides. Même si vous pouvez obtenir un fonctionnement à point fixe aussi rapide qu’un FPU "normal", le point réel à virgule flottante comporte des instructions avantageuses telles que fsel pour arrêter les branches ou SIMD pour travailler sur plusieurs flotteurs à la fois. Les GPU utilisent également la virgule flottante, au moins dans leurs interfaces utilisateur.
Deuxièmement, 64 bits vous amène également assez loin en virgule flottante - la plupart des gens utilisent encore 32, mais l’avantage principal est qu’ils évoluent. Cette échelle à points fixes a une précision fixe. Que vous mesuriez le soleil en direction de Pluton ou de l’autre côté de la rue, vous obtenez la même précision. La virgule flottante vous donnera des résultats beaucoup plus précis lorsque toutes les valeurs impliquées sont plus petites. Étant donné que les bibliothèques de physique génériques sont censées fonctionner de manière passable avec de nombreux jeux à différentes échelles (et que certains d'entre eux peuvent avoir des échelles très différentes), ils doivent utiliser une sorte de nombre qui fonctionne à plusieurs échelles.
la source
Un autre point important à souligner est que les flotteurs ne sont pas si inexacts que les gens ici semblent le penser. Un float de 32 bits a une précision entière de 24 bits sur 24 bits. Cela signifie qu’elle est au moins aussi précise que la valeur d’un point fixe à 24 bits pour une plage donnée. Tandis que les flottants deviennent moins précis plus la valeur est grande, une valeur de point fixe débordera tout simplement et s’enroulera à un moment donné. Réduire la précision est une meilleure solution de secours. Les flotteurs peuvent aussi déborder, mais beaucoup plus tard. Je voudrais voir vos visages lorsque votre monde s’enroulera soudainement à -2 ^ 31 en raison d’un débordement de points fixes.
Les valeurs à virgule flottante de 64 bits ont une précision entière de 53 bits, elles sont donc vraiment précises.
la source
Dans un contexte FPS, les valeurs en points fixes peuvent en réalité constituer un passif. Une virgule flottante proche de zéro est plus précise. Ce n'est que sur de grandes distances que le point fixe devient préférable. La réponse est simplement que cela dépend du contexte.
Dans quelque chose comme une galaxie, vous pouvez utiliser des cadres de référence. Utilisez une énorme échelle pour les systèmes solaires, puis utilisez le centre du Soleil (ou un point similaire) comme point de départ pour tout ce qui se trouve à l'intérieur du système. En utilisant ce système, vous pouvez avoir votre gâteau et le manger, pour ainsi dire, et ce n'est pas difficile à imaginer.
IIRC, le développeur d'Infinity, a déclaré qu'il abordait sans cesse les problèmes d'échelle dans l'une de ses interviews.
la source
Si vous ne l'avez pas encore fait, vous devriez définitivement consulter le tutoriel Planet Rendering sur GameDev.net. En ce qui concerne la division de l’espace, une solution consiste à conserver deux variables de position distinctes: une macro-échelle et une micro-échelle. Cela fonctionne très bien (testé).
La solution exacte dépend de la manière dont vous envisagez de gérer les distances extrêmes dans le moteur - planifiez-vous des barrières de saut ou une compression temporelle?
la source
Une des raisons est que l'arithmétique en virgule flottante est "assez bonne" (ou du moins l'a été), elle produit rapidement des résultats assez précis.
Tant que vous connaissez les limites de l'arithmétique en virgule flottante et que vous modifiez vos algorithmes pour y faire face (voir la réponse de Andrew Russell), vous produirez un code qui "fonctionne".
la source
J'écris un jeu. Dans mon jeu / programme, je dessine un vaisseau spatial à l'origine en utilisant une caméra relativement fixe et ma planète je dessine en utilisant une caméra séparée. Et ces deux choses règlent le problème pour moi, mais ma planète n’est pas encore très détaillée. En ce qui concerne la solution proposée par Andrew Russell au sujet du déplacement du monde (et je suppose que la caméra et ses habitants reviendront à l'origine), je n'essaierais vraiment pas cela si vous envisagiez de faire du jeu un jeu en réseau. Si vous déplaciez le monde sur l'application serveur en fonction des mouvements de chaque client, le monde finirait par avoir du mal à trouver un poste. Et prendrait sa position tout le temps de tout le monde jouer ce qui serait un énorme problème.
la source