Оптимизация производительности для 3D

Kepler.gl построен поверх WebGL-стека deck.gl, где каждая 3D-сцена формируется через слой (layer) с инстансированным рендерингом. Основная нагрузка в 3D-режиме возникает на трёх уровнях: геометрия, шейдеры и обновления состояния.

Геометрическая часть включает отрисовку миллионов точек, экструдированных полигонов, 3D-гексагонов и инстансированных объектов. Шейдерная нагрузка усиливается при использовании освещения, теней и наклонной камеры. Состояние приложения (viewport, filters, dataset) может приводить к повторной инициализации GPU-буферов при неправильной организации обновлений.


Ограничение объёма данных на уровне слоя

Основной принцип оптимизации 3D-рендеринга заключается в снижении количества активных инстансов, поступающих в WebGL-пайплайн.

Ключевые техники:

  • агрегация точек до визуальных примитивов (hexagon, grid, cluster layers)
  • предварительное уменьшение плотности данных на сервере или в worker-thread
  • использование порогов масштабирования (minZoom / maxZoom)
  • динамическое отключение слоёв вне зоны видимости

Особенно критичен переход от PointLayer к агрегированным слоям при данных выше сотен тысяч объектов. В 3D-режиме каждый дополнительный инстанс увеличивает нагрузку не линейно, а через рост работы vertex shader и fragment shader.


Использование агрегации вместо raw rendering

Hexagon и grid aggregation являются ключевыми инструментами стабилизации производительности. Вместо отрисовки отдельных точек выполняется предварительная свёртка данных.

Типичный эффект:

  • 1 000 000 точек → 10 000 гексагонов
  • снижение draw calls
  • уменьшение объёма GPU buffer attributes
  • стабильный frame rate при наклоне камеры

При работе с 3D extrusion особенно важно ограничивать elevationScale, так как высокие значения увеличивают визуальную сложность сцены и нагрузку на пиксельные шейдеры.


Управление уровнем детализации (LOD)

LOD-подход в Kepler.gl реализуется через сочетание zoom-dependent rendering и фильтрации данных.

Основные механизмы:

  • изменение геометрии слоя в зависимости от zoom
  • отключение 3D extrusion на низких масштабах
  • замена точек на агрегаты при удалении камеры
  • упрощение полигонов при низком zoom

Для экструдированных объектов критично ограничение количества вершин. Полигональные здания с высокой детализацией резко увеличивают стоимость rasterization stage при наклонённой камере.


Оптимизация обновлений состояния (state management)

Основной источник лишних перерисовок — частые изменения состояния visState.

Оптимизационные подходы:

  • иммутабельные обновления с минимальным diff
  • разделение состояния фильтров и данных
  • предотвращение перезаписи слоёв при изменении UI параметров
  • селективное обновление через мемоизацию селекторов

В архитектуре Kepler.gl любые изменения конфигурации слоёв могут триггерить пересоздание deck.gl layers, что приводит к повторной загрузке GPU буферов.


Снижение количества перерендеров React-слоя

Интеграция Kepler.gl с React требует строгого контроля ререндеров контейнера.

Ключевые методы:

  • использование useMemo для конфигураций слоёв
  • стабилизация ссылок на dataset objects
  • изоляция map component от UI state
  • предотвращение inline creation объектов config, filters, layers

Каждый новый reference в props может привести к полной реконструкции deck.gl scenegraph.


Оптимизация WebGL-пайплайна

В 3D-режиме основная нагрузка приходится на GPU:

  • vertex processing при экструдированных полигонах
  • fragment shading при освещении
  • depth buffer при наклонной камере

Практические оптимизации:

  • отключение lighting при высокой плотности данных
  • снижение opacity слоёв вместо сложных blend-режимов
  • минимизация использования alpha blending
  • использование простых цветов вместо gradient-шейдеров

Также критично уменьшение overdraw — количества перекрывающихся пикселей, особенно при высоком pitch камеры.


Управление камерой и viewport

Каждое изменение камеры (zoom, pitch, bearing) вызывает перерасчёт матрицы проекции и потенциальный redraw всех слоёв.

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

  • throttling событий движения камеры
  • separation of interactive and static layers
  • фиксирование pitch при массовой отрисовке
  • ограничение максимального наклона для 3D-сцен с высокой плотностью данных

Наклон камеры напрямую увеличивает количество пикселей, обрабатываемых fragment shader, что критично для экструдированных слоёв.


Работа с большими датасетами

При объёмах данных в миллионы записей основная стратегия — перенос вычислений из браузера:

  • предварительная агрегация на сервере
  • использование бинарных форматов вместо JSON
  • стриминг данных по тайлам
  • разделение датасетов по географическим регионам

JSON становится узким местом из-за парсинга и GC pressure. Более эффективны TypedArrays и precomputed buffers.


Instanced rendering и снижение draw calls

deck.gl использует instancing для большинства слоёв, однако эффективность зависит от структуры данных.

Оптимизационные принципы:

  • минимизация уникальных геометрий
  • группировка объектов по визуальным атрибутам
  • переиспользование buffer attributes
  • избегание динамического пересоздания layer props

Снижение draw calls имеет больший эффект, чем локальные оптимизации шейдеров.


Управление фильтрацией данных

Фильтры в Kepler.gl часто становятся причиной деградации производительности при неправильной реализации.

Ключевые подходы:

  • перенос фильтрации в Web Worker
  • кеширование результатов фильтров
  • применение фильтров до передачи в слой
  • избегание цепочек зависимых фильтров в runtime

Особенно затратны временные фильтры (time filters), которые требуют пересчёта наборов данных при каждом изменении диапазона.


Оптимизация 3D extrusion и геометрии зданий

Экструдированные полигоны являются одним из самых тяжёлых типов визуализации.

Методы оптимизации:

  • снижение количества вершин полигона (simplification)
  • ограничение максимальной высоты extrusion
  • отключение боковых граней при высокой плотности сцены
  • переход на flat shading вместо smooth shading

Геометрическая сложность зданий линейно увеличивает нагрузку на vertex shader и может приводить к bottleneck даже при небольшом количестве объектов.


Кеширование и переиспользование вычислений

Стабильность производительности достигается за счёт повторного использования промежуточных результатов:

  • кеширование агрегаций по zoom level
  • сохранение результатов кластеризации
  • мемоизация вычисленных color scales
  • переиспользование bounding boxes

При правильной организации кеша уменьшается количество CPU-bound операций перед отправкой данных в GPU.


Баланс между визуальной точностью и FPS

3D-визуализация всегда требует компромисса между детализацией и производительностью:

  • увеличение детализации → рост GPU нагрузки
  • упрощение геометрии → потеря точности
  • агрегация → снижение аналитической гранулярности

Стабильный рендеринг достигается через многоуровневую деградацию качества: от точек к агрегатам, от сложных полигонов к упрощённым формам, от динамического освещения к статическому цвету.