Архитектурные принципы

deck.gl построен вокруг декларативного подхода к описанию визуализации. Центральный принцип заключается в том, что разработчик описывает что должно быть отображено, а не как именно это рисовать шаг за шагом. Сцена представляется как набор слоёв, каждый из которых отвечает за отдельный аспект визуализации: точки, линии, полигоны, текстуры, 3D-объекты, пользовательские примитивы.

Декларативность обеспечивает предсказуемость состояния: при изменении данных или параметров слой автоматически пересчитывает своё представление, не требуя ручного управления WebGL-конвейером.

Ключевой эффект архитектурного решения — устранение прямой зависимости от низкоуровневого API WebGL в пользовательском коде. Это позволяет рассматривать визуализацию как функцию от входных данных:

visualization = f(data, viewState, layers)

Слоистая архитектура как фундамент системы

Основной структурный элемент deck.gl — слой (Layer). Архитектура построена на композиции слоёв, где каждый слой инкапсулирует:

  • обработку входных данных;
  • подготовку геометрии;
  • управление буферами GPU;
  • отрисовку через WebGL;
  • реакцию на изменения состояния.

Слои образуют иерархию абстракций. Базовый слой определяет общие механизмы жизненного цикла и взаимодействия с GPU, тогда как специализированные слои реализуют конкретные типы визуализации (например, ScatterplotLayer, ArcLayer, PolygonLayer).

Такое разделение позволяет расширять систему без модификации ядра, соблюдая принцип открытости/закрытости.


Разделение ядра и визуальных примитивов

Архитектура разделяет систему на два уровня:

1. Core (ядро):

  • управление сценой и контекстом WebGL;
  • оркестрация слоёв;
  • управление жизненным циклом;
  • обработка событий и состояния камеры;
  • оптимизация рендеринга.

2. Layers (слои):

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

Такое разделение снижает связанность компонентов и позволяет переиспользовать ядро для различных типов визуализации, включая 2D, 3D и геопространственные сцены.


Data-driven подход и реактивное обновление

Архитектура deck.gl ориентирована на работу с потоками данных. Каждый слой принимает массивы данных и параметры визуализации, после чего строит GPU-структуры.

Изменение входных данных автоматически триггерит перерасчёт только тех частей сцены, которые затронуты изменением. Это реализуется через диффинг свойств (props diffing) и контроль версий состояния слоя.

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

  • сравнение предыдущих и новых props;
  • инвалидация только изменённых атрибутов;
  • ленивое обновление буферов;
  • кэширование промежуточных вычислений.

Это позволяет масштабировать визуализацию до миллионов объектов без полного пересчёта сцены.


GPU-ориентированная архитектура

Ключевой принцип — максимальная разгрузка CPU за счёт переноса вычислений в GPU. Каждый слой оперирует WebGL-буферами напрямую:

  • position buffers;
  • color buffers;
  • index buffers;
  • instance attributes.

Шейдеры (vertex и fragment) становятся основным местом вычислений визуального представления. CPU выполняет только подготовку данных и управление состоянием.

Архитектура стремится минимизировать:

  • количество draw calls;
  • передачу данных между CPU и GPU;
  • пересоздание буферов.

Вместо этого используется инстансинг (instancing), позволяющий отрисовывать тысячи объектов одним вызовом рендера.


Атрибутная модель данных

Каждый слой определяет набор атрибутов, которые описывают геометрию и визуальные свойства объектов. Атрибуты делятся на:

  • геометрические (позиция, размер, направление);
  • визуальные (цвет, прозрачность);
  • служебные (id, индекс, состояние).

Атрибуты хранятся в GPU-буферах и обновляются только при изменении соответствующих данных.

Такой подход обеспечивает:

  • детерминированность визуализации;
  • эффективное использование памяти;
  • минимизацию синхронизации CPU/GPU.

Механизм жизненного цикла слоёв

Каждый слой проходит строго определённые стадии:

  1. инициализация ресурсов;
  2. получение и обработка данных;
  3. генерация атрибутов;
  4. создание/обновление WebGL буферов;
  5. рендеринг;
  6. освобождение ресурсов при удалении.

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

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


Иерархия представления и камера

Система координат и управление камерой являются отдельным архитектурным уровнем. Камера определяет:

  • положение наблюдателя;
  • угол обзора;
  • перспективу или ортографию;
  • трансформации сцены.

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

Это создаёт слабую связность между визуальными элементами и глобальной сценой.


Композиция слоёв и порядок рендеринга

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

  • порядком в массиве слоёв;
  • прозрачностью;
  • зависимостями между слоями;
  • настройками depth testing.

Композиционная модель позволяет строить сложные сцены из простых компонентов без модификации базовых слоёв.


Расширяемость через кастомные слои

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

  • определение собственных атрибутов;
  • реализацию методов обновления;
  • написание GLSL-шейдеров;
  • управление буферами.

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


Интеграция с реактивными UI-фреймворками

Архитектура deck.gl допускает интеграцию с React-подобными системами через концепцию реактивных props. Слой рассматривается как функция от состояния приложения.

Изменение состояния UI автоматически транслируется в изменение слоёв, что создаёт единый поток данных:

UI state → layers → GPU rendering

Это снижает сложность синхронизации визуализации и интерфейса.


Оптимизация производительности как часть архитектуры

Производительность не является внешним слоем, а встроена в архитектуру:

  • батчинг draw calls;
  • минимизация пересоздания буферов;
  • кэширование вычислений;
  • spatial indexing (в отдельных слоях);
  • инстансинг геометрии.

Особое внимание уделяется масштабированию: архитектура рассчитана на работу с большими наборами данных, где число объектов измеряется миллионами.


Абстракция геопространственных данных

Одним из ключевых сценариев является работа с геоданными. Архитектура включает:

  • поддержку координатных систем;
  • преобразование проекций;
  • работу с tile-based данными;
  • интеграцию с картографическими движками.

Слои могут оперировать как абстрактными координатами, так и привязанными к карте системами координат.


Событийная модель взаимодействия

Архитектура включает систему событий:

  • события навигации камеры;
  • взаимодействие с объектами сцены;
  • hover и click события;
  • изменение состояния слоёв.

События проходят через слой абстракции, который нормализует взаимодействие между WebGL и приложением.


Изоляция состояния и предсказуемость рендера

Каждый слой изолирует своё состояние. Это исключает побочные эффекты между слоями и делает рендеринг детерминированным.

Состояние делится на:

  • входные данные (immutable props);
  • внутреннее состояние (cache, buffers);
  • вычисленные атрибуты.

Такая модель упрощает отладку и повышает стабильность системы при сложных сценах.


Модульность и независимость компонентов

Архитектура построена на принципе модульности. Каждый слой является независимой единицей, которую можно:

  • подключать и отключать;
  • комбинировать с другими слоями;
  • переиспользовать в разных проектах.

Это позволяет строить библиотеку визуализаций как набор взаимозаменяемых компонентов.


Шейдерная архитектура как часть системы

Шейдеры являются полноценной частью архитектуры, а не вспомогательным элементом. Они:

  • генерируются или параметризуются слоями;
  • используют атрибуты как входные данные;
  • определяют финальное отображение пикселей.

Такой подход позволяет варьировать визуализацию без изменения JavaScript-логики слоя.


Абстракция над WebGL

Одним из ключевых архитектурных решений является скрытие сложности WebGL. Вместо прямого управления контекстом:

  • управление буферами автоматизировано;
  • жизненный цикл ресурсов контролируется системой;
  • синхронизация состояния выполняется ядром.

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