Недавно столкнулся с проблемой точности представления чисел с плавающей точкой при рендеринге тайловой сетки:
1. На вход поступают значения -1..1, двойной точности. Максимальная используемая точность - 2^26
2. Они как float передаются на рендер. float нормально может хранить только 2^23
3. Множатся на одну матрицу, в которой зашит и scale и translate и projection.
4. На выходе - очень большие ошибки, пиксели плавают по +-4 во все стороны :(
Не хватает точности float ни для передачи координат тайлов, ни для передачи матрицы - числа "округляются" где-то далеко, но важно, после запятой.
Идея номер 1 - передавать координаты тайлов не через float, а через uint - получаем гарантированную точность 2^32, маппинг в "старые" координаты как 1/N
Идея номер 2 - отказаться от матриц, передавать трансформацию исходными параметрами - viewport, zoom, center
Получаем координату тайла. Делим на zoomfactor, потом уже этим значением делим единицу - сразу нельзя, так как потеряем и так не гарантированную точность.
Что смущает:
1. Насколько я знаю - что либо кроме float может приводить к падению производительности в разы. Специфично для конкретного девайса, или драйвера - но опасность есть. Или с этим уже нормально?
2. Отказ от нормальных матриц убирает многие свистелки и перделки :(
Альтернативное решение - разбитие исходной карты на N сегментов таким образом, чтобы в каждом из них точности представления float хватало для точной адресации тайлов. Но это уже немного сложнее реализовывать.
Что может посоветовать %username%, особенно если работать должно и на девайсах с точностью mediump?
Чет подозрительно. Что рисуешь то хоть?
Ландшафт, большой, тайлами. Стандартные источники тайлов отдают их до 18 зума + 256 пикселей размер самого тайла.
Итого точность позиционирования 2^26 (18+8).
Проблема известная, начинают прыгать плоскости треугольников. Решение, нужно строить вершины объектов, и его положение, относительно камеры.
То есть на рендер ты посылаешь не вершины или положение относительно мировых координат (достаточно посчитать положения объекта/сегмента относительно камеры), а вычитаешь из них положение камеры - камера автоматом становится в нулевых координатах.
Но это половина решения его хватить для того чтобы вершины посчитать используя double и спокойно преобразовать во float, для больших масштабов тебе придется перестраивать мировую систему координат.
С увеличением масштабов начнет неправильно позиционироваться сама камера, то есть double будет не достаточно, это тоже решаемо в иерархической системе координат. Мировая система координат делится на сегменты, имеющие свою локальную систему отсчета, и камера перемещается между этими сегментами.
Kashey
> Ландшафт, большой, тайлами
Тайлами? То есть, двухмерный, вид сверху?
Именно так.
Kashey
Считай координаты ландшафта целочисленно, а кусок, на который смотришь, перегоняй во float. Например, с нулем в центре камеры, да. Ну или еще как-то еще, чтобы по-реже перегонять.
Kashey
> Что может посоветовать %username%, особенно если работать должно и на девайсах
> с точностью mediump?
Это что за девайсы? По-моему в вершинных шейдерах везде есть highp. Его только во фрагментных шейдерах может не быть.
-Eugene-
Да хотелось бы избежать сей практики.
gammaker
Яж не настоящий сварщик. Но говорят, старые дроиды....
Тема в архиве.