Буферизация в deck.gl представляет собой фундаментальный слой работы с данными, на котором строится высокая производительность визуализации. Вся геометрия, отображаемая слоями, в конечном итоге преобразуется в GPU-буферы — структуры WebGL, содержащие упакованные массивы вершин, индексов и атрибутов. Эти буферы определяют, как именно данные будут интерпретированы видеокартой при рендеринге примитивов.
В основе буферизации лежит преобразование JavaScript-объектов в TypedArray-структуры. Deck.gl минимизирует количество операций на CPU, перекладывая вычисления на этап подготовки атрибутов.
Каждый слой (Layer) определяет собственную схему атрибутов:
Буфер создаётся один раз при инициализации слоя и переиспользуется при обновлениях данных, если не изменяются зависимости.
Ключевая идея — иммутабельность буфера при отсутствии изменений данных. Это позволяет избегать дорогостоящих пересозданий GPU-ресурсов.
Центральным компонентом управления буферизацией является AttributeManager. Он отвечает за:
Атрибут описывается как генератор данных из исходного массива объектов:
Буфер обновляется не целиком, а по необходимости. Если изменился только цвет объектов, геометрические буферы не пересчитываются.
Deck.gl использует бинарный формат представления данных как внутренний стандарт. Вместо массива объектов:
[
{x: 0, y: 0, z: 0, color: [255, 0, 0]},
{x: 1, y: 1, z: 0, color: [0, 255, 0]}
]
данные преобразуются в:
Такой подход снижает накладные расходы на обращение к памяти и улучшает кэш-локальность.
Перед загрузкой в буферы геометрия проходит серию преобразований. Эти операции зависят от типа слоя.
Многие слои требуют приведения координат к единому пространству:
Проекция выполняется на этапе attribute calculation, что позволяет избежать повторных вычислений в шейдерах.
Для полигональных слоёв (PolygonLayer, GeoJsonLayer) используется разбиение на треугольники. Основной алгоритм — ear clipping (ушная триангуляция).
Процесс включает:
Результатом является индексный буфер, минимизирующий дублирование вершин.
Для линейных слоёв (PathLayer, LineLayer) геометрия преобразуется в набор сегментов. Каждая линия разбивается на:
Это позволяет отрисовывать линии с переменной толщиной через GPU без CPU-растеризации.
Instanced rendering является ключевой оптимизацией. Один набор геометрии (например, сфера или куб) используется многократно.
Буферы делятся на:
Instance attributes включают:
GPU получает один draw call для тысяч объектов, что существенно снижает overhead WebGL.
Deck.gl использует дифф-алгоритм обновления атрибутов. При изменении props слоя:
Пример логики:
Это позволяет поддерживать интерактивность при больших наборах данных.
Часть операций выполняется на GPU, часть — на CPU.
CPU-стадия:
GPU-стадия:
Разделение обязанностей снижает нагрузку на основной поток JavaScript.
Deck.gl опирается на строго типизированные массивы:
Особенность подхода:
Index buffer (ELEMENT_ARRAY_BUFFER) позволяет избегать дублирования геометрии. Вместо повторного описания каждой вершины:
Это критично для:
Экономия памяти растёт пропорционально сложности геометрии.
Каждый слой использует матрицы преобразований:
Вершины буфера передаются в шейдер уже в локальной системе, после чего преобразуются в clip-space.
Часто используется матрица:
Некоторые слои не используют входную геометрию напрямую:
Они генерируют буферы процедурно:
Буферизация здесь происходит после агрегации данных.
WebGL-буферы являются ограниченным ресурсом, поэтому применяется:
При изменении размера данных:
Picking требует отдельного набора буферов:
Каждый пиксель сцены кодирует идентификатор объекта через цветовую упаковку. Это позволяет выполнять выбор объектов без CPU-итерации по массиву данных.
GeoJSON-данные проходят несколько стадий:
Особое внимание уделяется вложенным структурам и неоднородным типам геометрии.
При работе с внешними источниками данных часто используются:
Перед буферизацией данные восстанавливаются в Float32Array, после чего проходят стандартный pipeline атрибутов.
Финальный этап включает:
Буферы становятся источником данных для vertex shader, который выполняет финальную геометрическую трансформацию перед растеризацией.