Одна из проблем при разработке игр с большими игровыми мирами заключается в том, что объекты начинают дрожать и телепортироваться по мере удаления от начала мира. Разработчики Godot Engine преодолели эту проблему, и реализовали эмуляцию двойной точности на графическом процессоре для рендеринга больших миров.
По умолчанию Godot использует числа с плавающей запятой одинарной точности для хранения таких вещей, как позиции объектов. Хотя GDScript обычно позволяет пользователям выполнять вычисления в пользовательском пространстве с двойной точностью, эти вычисления усекаются, как только они сохраняются во внутренних объектах Godot (например, в Vector3).
Это было проблемой для пользователей, которые хотели делать такие вещи, как создание игр в масштабах солнечной системы. Пользователи быстро сталкивались с ошибками точности с плавающей запятой и замечали, что движение становится дрожащим (персонаж телепортируется из точки в точку), а объекты рассыпаются.
10000 км – это 10 миллионов единиц от исходной точки. При 10 миллионах единиц мы имеем примерно 1 единицу точности. Это означает, что расстояние между каждой позицией, которую может сохранить Vector3, составляет около 1 метра. На 1000 км точность составляет всего 6,25 см, чего недостаточно даже для простой сцены.
Как найти решение? Т.к. проблема возникла из-за использования одинарной точности во внутренних классах Godot, поэтому решение должно состоять в том, чтобы вместо этого использовать двойную точность.
В Godot 4.0 разработчики представили возможность компилировать движок с числами с двойной точностью, чтобы все вычисления происходили с гораздо более высокой точностью.
Решение было простым – использовать двойники во всех шейдерах. Нужны только удвоения при расчете MODELVIEW_MATRIX, которая отвечает за две функции: преобразование из предметного пространства в мировое пространство, трансформация из мирового пространства в пространство камеры. При реализации не нужна двойная точность в пространстве объектов или пространстве камеры, потому что модели невелики и ничто не находится очень далеко от камеры. Собирается MODELVIEW_MATRIX в вершинном шейдере путем объединения объектов MODEL_MATRIX и камер VIEW_MATRIX.
Но Metal (графический API, используемый на всех устройствах Apple) не поддерживает использование двойников в шейдерах, поэтому это не будет работать на устройствах Apple. Многие устройства сторонних производителей по-прежнему борются с двойной точностью на графическом процессоре. Т.е. нельзя просто "включить" двойников и всё волшебным образом заработает на всех GPU.
Решение было найдено в том, что не нужны удвоения для выполнения операции с высокой точностью, вместо этого достаточно эмулировать двойную точность, используя числа с плавающей запятой с двойной одинарной точностью. И не нужно вычислять полное значение MODELVIEW_MATRIX с двойной точностью, можно отделить преобразование вращения/масштабирования от преобразования перемещения и выполнять преобразование только с двойной точностью.
Так многие уже реализовывали обычные операции почти с двойной точностью, используя всего пару чисел с плавающей запятой одинарной точности. Тот же базовый прием можно использовать даже для создания произвольной точности из чисел с плавающей запятой или двойных чисел. Например, такие библиотеки, как LibQuadMath, эмулируют 128-битную точность, используя два двойных числа.
Т.е. все числа с плавающей точкой могут быть преобразованы в двойные без потери точности. Поскольку это нужно только для операции перевода, просто нужно передать дополнительную Vector3 матрицу камеры и дополнительную Vector3 матрицу модели. Затем при преобразовании модели в пространство камеры вместо вычисления MODELVIEW_MATRIX, разделить преобразование на отдельные компоненты и выполнить вращение/масштабирование отдельно от перемещения.
Это решение, на котором разработчики движка Godot остановились, оставшись довольными найденными компромиссами. Это решение должно работать на всём поддерживаемом оборудовании и должно снижать производительность лишь на небольшую величину. Однако есть пара ограничений:
Это не работает с skip_vertex_transform режимом рендеринга: другими словами, пользователи должны использовать путь по умолчанию, где Godot обрабатывает модель для просмотра трансформации пространства.
Пользователи не могут выполнять математические вычисления шейдеров в мировом пространстве: пользовательские шейдеры по-прежнему будут ограничены плавающей запятой с одинарной точностью, поэтому вычисления в мировом пространстве по-прежнему будут подвержены артефактам низкой точности.
Это относится только к проблемам точности с позиции объекта. Другими словами, это не исправит вашу сферу размером с Землю, для положения вершин модели вам все равно придется обойти ограничения одинарной точности с плавающей запятой.
Это изменение уже включено в движок, однако оно доступно только в "двойной" версии движка, поэтому, чтобы воспользоваться им, вам все равно придется собрать движок самостоятельно, используя флаг компиляции "float= 64".
Также если вы считаете, что данный материал мог быть интересен и полезен кому-то из ваших друзей, то вы бы могли посоветовать его, отправив сообщение на e-mail друга:
Игровые объявления и предложения:
Если вас заинтересовал материал «Двойная точность на GPU для больших миров в Godot», и вы бы хотели прочесть что-то на эту же тему, то вы можете воспользоваться списком схожих материалов ниже. Данный список сформирован автоматически по тематическим меткам раздела.
Предлагаются такие схожие материалы:
Если вы ведёте свой блог, микроблог, либо участвуете в какой-то популярной социальной сети, то вы можете быстро поделиться данной заметкой со своими друзьями и посетителями.
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи. [ Регистрация | Вход ]