С плавающей точкой всегда было трудно из-за точности в больших мирах.
Эта статья объясняет закулисные и предлагает очевидную альтернативу - числа с фиксированной запятой. Некоторые факты действительно впечатляют, например:
«Точность 64 бита дает вам расстояние до Плутона от Солнца (7,4 млрд. Км) с точностью до субмикрометра».
Точность субмикрометра больше, чем нужно для fps (для позиций и даже скоростей), и это позволит вам создавать действительно большие миры.
Мой вопрос: почему мы все еще используем плавающую точку, если у фиксированной точки есть такие преимущества? Большинство API рендеринга и физические библиотеки используют с плавающей запятой (и страдают от его недостатков, поэтому разработчики должны обойти их).
Они намного медленнее?
Кроме того, как вы думаете, масштабируемые планетарные двигатели, такие как externalra или infinity, справляются с большими масштабами? Используют ли они фиксированную точку для позиций или у них есть некоторый алгоритм разделения пространства?
Ответы:
Если вы позволите мне бесстыдный плагин, я приведу вам пример из реальной игры, над которой я работаю (ссылка на видео YouTube).
В игре есть бесконечный процедурный мир, созданный на физическом движке. Он использует плавающую точку одинарной точности. После нескольких сотен метров игрового пространства начинают возникать проблемы с точностью (и чем дальше от исходной точки вы становитесь все хуже).
Мое решение? Каждые 200 м или около того я перемещаю весь мир назад на 200 м к исходной точке (если вы захотите найти и попробовать один из прототипов на моем сайте и вызвать наложение [w] orld debug, вы можете увидеть, как это происходит).
Почему бы не использовать фиксированную точку? Или двойная точность? Вместо одинарной точности? Потому что все остальное использует одинарную точность с плавающей точкой!
Используемый мной физический движок использует его, XNA использует, данные, которые загружаются на видеокарту, форматируются как плавающая точка одинарной точности. Даже сам язык предназначен для работы с числами с плавающей запятой - писать и (что более важно) читать
0.5f
гораздо проще, чем0x80000000L
.Это просто вопрос того, что легче на практике. И абсолютный победитель знает о проблемах точности с плавающей запятой и пишет довольно простые функции «переместить мир назад к нулю» (или реализуя разбиение пространства или что-то подходящее вашей игре).
И, наконец, еще один пример - Orbiter - это игра (действительно симуляция), которая действительно должна заботиться о точности. Не только в пространстве, но и во времени (ускорение времени плюс вращающиеся тела - не хочу, чтобы они падали с неба, сейчас). Он также использует числа с плавающей запятой и использует хак для поддержания стабильности.
источник
Во-первых - да, они значительно быстрее. Даже если вы можете заставить фиксированную точку работать так же быстро, как и «обычный» FPU, реальная плавающая точка имеет полезные инструкции, такие как fsel, чтобы остановить ветвление, или SIMD, чтобы работать на многих поплавках одновременно. Графические процессоры также используют числа с плавающей запятой, по крайней мере, в своих пользовательских интерфейсах.
Во-вторых, 64-битная система дает вам достаточно большие результаты с плавающей запятой - большинство людей по-прежнему используют 32-разрядную версию, но основное преимущество заключается в том, что она масштабируется. Эта шкала с фиксированной точкой имеет фиксированную точность. Измеряете ли вы Солнце до Плутона или через улицу, вы получаете одинаковую точность. Плавающая точка даст вам гораздо более точные результаты, когда все значения меньше. Поскольку библиотеки общей физики, как ожидается, будут работать по крайней мере сносно с большим количеством игр в разных масштабах - а сами игры могут иметь совершенно разные масштабы - им нужно использовать некое число, которое работает во многих масштабах.
источник
Еще один важный момент: поплавки не так неточны, как думают люди здесь. 32-разрядное число с плавающей запятой имеет 24-разрядную целочисленную точность. Это означает, что оно является по меньшей мере таким же точным, как 24-битное значение с фиксированной точкой для любого заданного диапазона. В то время как значения с плавающей точкой становятся менее точными, чем больше значение, тем больше значение с фиксированной точкой будет просто переполнено и обернуто в некоторой точке Снижение точности - лучший запасной вариант. Поплавки тоже могут переполниться, но далеко-далеко позже. Я хотел бы видеть ваши лица, когда ваш мир внезапно приближается к -2 ^ 31 из-за переполнения фиксированной точки.
64-битные значения с плавающей запятой имеют 53-битную целочисленную точность, поэтому они действительно точные.
источник
В контексте FPS значения с фиксированной запятой могут фактически являться обязательством. Близкое к нулю с плавающей точкой является более точным. Именно на больших расстояниях фиксированная точка становится более предпочтительной. Ответ прост, это зависит от контекста.
В чем-то вроде галактики вы можете использовать системы отсчета. Используйте огромный масштаб для солнечных систем, а затем используйте центр Солнца (или подобную точку) в качестве отправной точки для чего-либо внутри системы. Используя эту систему, вы можете съесть свой пирог и съесть его, так сказать, и его нетрудно представить.
IIRC, разработчик Infinity, заявил, что в одном из своих интервью он постоянно перебирал вопросы масштаба.
источник
Если вы еще этого не сделали, вам обязательно нужно ознакомиться с руководством по рендерингу планет на GameDev.net. Что касается разделения пространства, одним из решений является сохранение двух отдельных переменных положения - одного макромасштаба и одного микромасштаба. Это работает довольно хорошо (проверено).
Точное решение зависит от того, как вы планируете обрабатывать экстремальные расстояния в двигателе - планируете ли вы прыжковые ворота или сжатие времени?
источник
Одна из причин заключается в том, что арифметика с плавающей точкой является «достаточно хорошей» (или, по крайней мере, таковой была), она быстро дает довольно точные результаты.
Пока вы знаете об ограничениях арифметики с плавающей запятой и меняете свои алгоритмы, чтобы справиться с ними (см. Ответ Эндрю Рассела), вы будете создавать код, который «работает».
источник
Я пишу игру. В моей игре / программе я рисую космический корабль в начале координат, используя довольно фиксированную камеру, а мою планету я рисую, используя отдельную камеру. И эти две вещи решают проблему для меня, но моя планета еще не очень детализирована. Что касается решения, которое Эндрю Рассел упомянул о перемещении мира (и я предполагаю, что камера и ее обитатели возвращаются к исходной точке), я бы на самом деле не пытался, если бы вы когда-нибудь планировали сделать игру сетевой игрой. Если бы вы перенесли мир на серверное приложение, основываясь на движениях каждого клиента, тогда мир в конечном итоге боролся бы за свою позицию. И все время занимал бы свою позицию у всех, кто играл, что было бы огромным затруднением.
источник