Как стать автором
Обновить

Оптимизируем работу с уровнями детализации 3D модели (LOD)

Время на прочтение2 мин
Количество просмотров1.9K
Пример LOD из данного урока
Пример LOD из данного урока

В данном уроке расскажу о своем способе организации работы с уровнями детализации 3D объектов. Не претендую на новаторство. Делюсь своим опытом.

При разработке своего сервиса для встраивания 3D моделей на сайты стояла задача оптимизации процесса рендеринга всеми возможными способами. Одним из таких является технология LOD, когда мы показываем модель с разной детализацией в зависимости от расстояния камеры до объекта.

Стандартный метод

Первое что приходит на ум – для каждого диапазона приближения подгружать целиком модель с нужным количеством полигонов. Но такой подход мне показался не совсем рациональным. Ведь у модели могут быть части, которые не требуют изменения в деталях, и их может быть достаточно много, а мы их будем многократно подгружать без полезного эффекта.

Таким образом, при стандартном подходе к LOD мы можем зря расходовать память при хранении разных вариантов модели и увеличивать время их загрузки.

Оптимизация LOD

Мне пришла в голову следующая идея хранения информации о деталях модели:

  • Для первого уровня детализации мы храним в отдельном файле все меши нашей 3D модели с минимальным числом полигонов.

  • Для последующих уровней храним в соответствующих файлах только те меши, где детализация была изменена.

Далее получаем следующий алгоритм сборки нашего 3D объекта в зависимости от текущего уровня детализации:

  • Загружаем модель начального LOD

  • Определяем текущий уровень детализации на основе дистанции до объекта

  • Загружаем вариант модели нового уровня, если он еще не был загружен

  • Пробегаемся от начального уровня до текущего и последовательно заменяем геометрии мешей соответствующих уровней

Ниже приведу код последнего шага алгоритма (под капотом three.js):

for (let i = 0; i <= newLodLevel; i++)
{
  const level = this.lodLevels.get(i);
  
  level.meshes.forEach(mesh =>
  {
    const model = this.model.item(mesh.name);
    const geometry = i === 0 ? mesh.userData.geometryInit : mesh.geometry;
    model.setGeometry(geometry, {notUpdateGeometry: true});
  });
}

Из важных нюансов данного фрагмента реализации алгоритма – для начального уровня мы берем геометрию начального состояния мешей (предварительно склонировали геометрию в userData.geometryInit).

Итого

Благодаря проведенной оптимизации стандартного подхода мы экономим память и ускоряем загрузку деталей.

Результат работы данного алгоритма можно посмотреть на примере.

Буду благодарен обратной связи по моему алгоритму. Надеюсь, что кому-то он будет полезен в своих проектах.

Теги:
Хабы:
Всего голосов 1: ↑0 и ↓1-1
Комментарии2

Публикации

Истории

Ближайшие события

27 августа – 7 октября
Премия digital-кейсов «Проксима»
МоскваОнлайн
28 сентября – 5 октября
О! Хакатон
Онлайн
3 – 18 октября
Kokoc Hackathon 2024
Онлайн
10 – 11 октября
HR IT & Team Lead конференция «Битва за IT-таланты»
МоскваОнлайн
25 октября
Конференция по росту продуктов EGC’24
МоскваОнлайн
7 – 8 ноября
Конференция byteoilgas_conf 2024
МоскваОнлайн