Viewport culling

Viewport culling в Deck.gl представляет собой ключевой механизм оптимизации рендеринга, основанный на исключении объектов, находящихся вне текущей области видимости камеры. В контексте высокопроизводительной визуализации больших наборов данных этот механизм определяет разницу между интерактивным приложением и системой, не справляющейся с нагрузкой даже при умеренном объёме геометрии.

Viewport culling опирается на геометрическое соотношение объектов сцены и текущего состояния камеры. В терминах WebGL-сцены каждый кадр характеризуется параметрами:

  • координаты центра камеры
  • угол обзора
  • матрица проекции
  • размеры viewport

Любой объект сцены может быть представлен через ограничивающий объём (bounding volume), чаще всего axis-aligned bounding box (AABB) или bounding sphere. Основная задача culling — определить пересечение этих объёмов с видимой областью (view frustum).

Если объект полностью находится вне фрустума, он исключается из pipeline рендеринга до этапа передачи в GPU.

View Frustum и его математическая модель

View frustum представляет собой усечённую пирамиду, задаваемую шестью плоскостями:

  • left
  • right
  • top
  • bottom
  • near
  • far

Каждая плоскость описывается уравнением:

ax + by + cz + d = 0

Положение точки относительно плоскости определяется знаком выражения:

f(x,y,z) = ax + by + cz + d

Если значение функции для всех вершин bounding volume отрицательно относительно одной из плоскостей, объект считается вне видимости.

В системах типа Deck.gl этот этап выполняется на CPU до передачи данных в WebGL pipeline, что позволяет существенно снизить нагрузку на GPU.

Архитектура culling в Deck.gl

Внутренняя архитектура viewport culling основана на разделении ответственности между слоями (layers), геометрическими источниками данных и системой координат viewport.

Основные этапы:

  1. Подготовка данных слоя
  2. Преобразование координат в clip space
  3. Проверка bounding volumes
  4. Исключение невидимых объектов
  5. Передача отфильтрованного набора в WebGL

Каждый слой в Deck.gl реализует собственную стратегию culling, адаптированную под тип данных: точки, линии, полигоны, тайлы.

Clip space и нормализация координат

После применения матрицы модели, вида и проекции (MVP matrix) координаты переводятся в clip space:

v_{clip} = M_{projection} M_{view} M_{model} v

В этом пространстве применяется перспективное деление:

финальная проверка попадания в диапазон видимости:

-1 x,y,z

Любые объекты, выходящие за эти пределы полностью, исключаются из рендеринга.

CPU-based culling vs GPU-based culling

В системах визуализации существует два основных подхода:

CPU culling

В Deck.gl основной подход — предварительная фильтрация на CPU. Преимущества:

  • снижение количества draw calls
  • уменьшение объёма передаваемых данных в GPU
  • возможность сложной логики отсечения

Недостатки:

  • нагрузка на JavaScript-движок
  • ограниченная параллелизация (хотя используется worker-подход)

GPU culling

Альтернативный подход предполагает использование compute shaders или vertex shaders для отсечения. Он применяется реже в Deck.gl из-за архитектурных ограничений WebGL 1/2 и необходимости совместимости.

Spatial indexing и ускорение culling

Viewport culling становится эффективным только при наличии пространственной индексации. В Deck.gl применяются структуры:

  • quadtrees
  • grid-based spatial hashing
  • R-tree (в пользовательских реализациях)

Quadtrees особенно эффективны для географических данных, где плотность точек неравномерна. Узлы дерева агрегируют bounding boxes, что позволяет исключать целые группы объектов одним тестом пересечения.

Tile-based culling

Для больших картографических наборов данных применяется tile-based стратегия. Каждый тайл имеет собственный bounding box, и проверка выполняется на уровне тайлов, а не отдельных объектов.

Псевдологика:

  • если tile вне frustum → пропустить весь набор
  • если tile частично видим → детализировать и проверить внутри

Такой подход особенно важен при работе с миллионами точек или линий.

Оптимизация через screen-space error

В дополнение к геометрическому culling применяется screen-space error оценка. Объекты могут быть исключены даже при попадании во фрустум, если их вклад в изображение ниже порога пиксельной значимости.

Метрика:

error =

Если error меньше заданного threshold, объект не рендерится.

Layer-level culling в Deck.gl

Каждый слой в Deck.gl реализует culling на уровне своей абстракции.

ScatterplotLayer

Для точечных данных используется bounding box по набору точек. Проверка выполняется батчами, что минимизирует overhead.

PathLayer

Линии разбиваются на сегменты, и каждый сегмент проверяется отдельно. Это позволяет исключать части длинных географических маршрутов.

PolygonLayer

Полигональные структуры используют convex hull или предварительно вычисленные bounding boxes. Дополнительно применяется тест пересечения с frustum planes.

Temporal culling и динамические данные

В сценариях с анимацией или потоковыми данными viewport culling дополняется временной фильтрацией. Объекты могут быть исключены не только по пространству, но и по времени жизни.

Типичный кейс — визуализация треков:

  • устаревшие точки удаляются
  • новые добавляются в буфер
  • culling применяется только к активному окну времени

Interaction between culling and picking

Механизм picking (выбор объектов) тесно связан с viewport culling. При отключённом culling увеличивается пространство поиска для hit-testing. При активном culling уменьшается число кандидатов, что ускоряет интерактивные операции.

Однако чрезмерное агрессивное отсечение может приводить к потере точности при hover-событиях, особенно для объектов на границе frustum.

Precision issues и floating point limitations

При больших географических координатах возникает проблема точности float32. Viewport culling должен учитывать:

  • округления при проекциях
  • ошибки матриц трансформации
  • дрейф bounding box при масштабировании

В Deck.gl используются стратегии floating origin и локализации координат относительно viewport центра, что уменьшает накопление ошибок.

Batch processing и WebGL pipeline

Culling напрямую влияет на количество батчей, отправляемых в GPU. Каждый оставшийся объект после отсечения попадает в render batch.

Оптимизация заключается в:

  • объединении геометрий
  • instancing
  • минимизации переключений state machine WebGL

Таким образом viewport culling становится предшествующим этапом всей графической оптимизации.

Adaptive culling strategies

В зависимости от zoom level и плотности данных применяются адаптивные стратегии:

  • при низком zoom уровне: агрессивное агрегирование
  • при высоком zoom уровне: точечная детализация

Это позволяет поддерживать стабильный frame rate при изменении масштаба сцены.

Математически это можно выразить через функцию зависимости детализации: