Uniforms и attributes

В Mapbox GL JS система рендеринга основана на WebGL-пайплайне, в котором каждая визуальная сущность преобразуется в набор вершинных данных (attributes) и параметров шейдера (uniforms). Эти два механизма формируют основу того, как слои карты превращаются в пиксели: attributes определяют геометрию и вариативные данные на уровне вершин, а uniforms задают глобальные параметры отрисовки, общие для всего draw-call или слоя.

В WebGL-модели, используемой Mapbox GL JS, каждый слой карты компилируется в один или несколько шейдеров. Эти шейдеры оперируют двумя типами входных данных:

  • Attributes — данные, привязанные к вершинам (vertex-level data)
  • Uniforms — глобальные параметры, одинаковые для всех вершин в пределах одного вызова отрисовки

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

Vertex attributes в Mapbox GL JS

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

Типичные vertex attributes включают:

  • координаты позиции вершины в пространстве тайла
  • параметры смещения (для линий и обводок)
  • данные для интерполяции (цвет, ширина, уровень экструдирования)
  • служебные значения для стилизации и фильтрации

Внутренне геометрия преобразуется в буферы WebGL, где каждая вершина представляется структурой фиксированного формата. Например, для линейного слоя могут использоваться атрибуты наподобие:

  • позиция вдоль линии
  • нормаль к сегменту
  • прогресс вдоль линии (line progress)

Для полигональных слоёв и заливок используются атрибуты, позволяющие корректно обрабатывать триангуляцию и внутренние границы полигона.

Атрибуты векторных тайлов

Vector Tile спецификация предполагает хранение геометрии в виде команд (moveTo, lineTo, closePath), которые при декодировании превращаются в набор вершин. Mapbox GL JS дополнительно обогащает эти данные:

  • a_pos — позиция вершины в координатах тайла
  • a_extrude — направление экструдирования (особенно важно для fill-extrusion)
  • a_data — упакованные служебные параметры
  • a_color — предварительно интерполированные значения цвета (в некоторых пайплайнах)

Каждый слой использует собственный layout атрибутов, формируемый на этапе компиляции стиля.

Преобразование layout и paint свойств в attributes

Часть style specification в Mapbox GL JS влияет на то, какие данные попадают в attributes. Layout-параметры, как правило, определяют структуру геометрии, тогда как paint-параметры чаще преобразуются в uniforms или интерполируемые атрибуты.

Примеры преобразований:

  • line-width может стать uniform или атрибутом в зависимости от наличия интерполяции
  • fill-color часто передаётся как uniform, если не зависит от вершинных данных
  • line-gradient требует атрибутов прогресса вдоль линии

Если свойство зависит от zoom, feature-state или expression, компилятор может выбрать стратегию:

  • uniform (глобальная константа для draw call)
  • attribute (вариативность на уровне вершин)
  • texture lookup (для сложных интерполяций)

Uniforms в Mapbox GL JS

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

Матрицы преобразования

Одними из ключевых uniforms являются матрицы трансформации:

  • матрица проекции (projection matrix)
  • матрица вида (view matrix)
  • матрица модели-мира (model-view transformation)
  • комбинированная матрица u_matrix

Эти матрицы обеспечивают перевод координат из пространства тайла в экранное пространство.

Камера и географическая проекция

Mapbox GL JS использует Web Mercator projection, где uniforms определяют параметры камеры:

  • центр карты
  • масштаб (zoom level)
  • наклон (pitch)
  • вращение (bearing)

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

Часто используются следующие uniform-переменные:

  • u_zoom — текущий уровень масштабирования
  • u_center — центр карты в нормализованных координатах
  • u_bearing — угол поворота
  • u_pitch — наклон камеры
  • u_pixels_per_meter — коэффициенты масштабирования

Тайловая система и uniforms

Каждый векторный тайл рендерится с собственным набором uniforms, описывающих его положение в сетке:

  • координаты тайла (z/x/y)
  • масштаб тайла относительно viewport
  • смещение тайла в пикселях
  • параметры clip-плоскостей

Эти uniforms позволяют шейдеру корректно совмещать множество тайлов в единой сцене.

Динамические uniforms и состояние времени

Некоторые визуальные эффекты требуют временного параметра:

  • анимация линий
  • пульсация символов
  • эффекты воды или свечения

В таких случаях используется uniform времени:

  • u_time — монотонно увеличивающееся значение времени

Это позволяет реализовывать эффекты без изменения vertex buffers, полностью на стороне GPU.

Feature-state и uniforms

Mapbox GL JS поддерживает механизм feature-state, позволяющий изменять визуальные свойства отдельных объектов без пересборки источника данных.

При этом:

  • часть данных кодируется в attributes
  • часть передаётся как uniforms через lookup-текстуры или uniform массивы

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

Взаимодействие attributes и expressions

Expression-система Mapbox GL JS компилируется в комбинацию:

  • uniform-значений для константных частей выражений
  • атрибутов для feature-dependent значений
  • ветвлений и интерполяций внутри шейдера

Например, выражение интерполяции цвета по zoom может быть разложено в:

  • uniform текущего zoom
  • атрибуты stop-значений
  • линейную интерполяцию в фрагментном шейдере

Атрибуты в символических слоях

Symbol layers используют более сложные атрибуты, связанные с текстом и иконками:

  • позиция символа
  • угол поворота
  • приоритет столкновений (collision ranking)
  • размеры SDF-иконок

Эти данные активно используются в layout-фазе, где выполняется размещение объектов до стадии рендеринга.

Fill-extrusion и специализированные attributes

3D-слой экструзии полигонов использует дополнительные vertex attributes:

  • направление нормали поверхности
  • высота экструдирования
  • коэффициенты освещения

Каждая вершина полигона дублируется для верхней и нижней грани, а attributes определяют геометрию объёма.

Производительность и упаковка данных

Эффективность работы attributes и uniforms напрямую связана с упаковкой данных:

  • attributes кодируются в компактные бинарные буферы
  • используются normalized integers вместо float где возможно
  • уменьшается количество varying-переменных между vertex и fragment шейдером

Uniforms минимизируются, поскольку их изменение вызывает переключение состояния GPU.

Custom layers и управление uniforms/attributes

Custom layer API позволяет напрямую задавать собственные uniforms и attributes для WebGL-рендеринга поверх карты.

В этом случае:

  • uniforms задаются вручную при каждом render call
  • attributes формируются из пользовательских буферов
  • ответственность за синхронизацию ложится на внешний код

Такой подход используется для интеграции кастомных шейдеров, 3D-объектов и постобработки.

Связь с тайловым кешем и перерасчётом данных

Attributes зависят от данных тайлового кеша. При изменении стиля:

  • часть attributes пересобирается (re-style)
  • часть uniforms обновляется без перерасчёта геометрии

Это разделение позволяет Mapbox GL JS поддерживать плавную интерактивность даже при сложных стилевых изменениях.

Шейдерная модель исполнения

В итоговом WebGL-пайплайне:

  1. Attributes загружаются в vertex buffer
  2. Uniforms устанавливаются для draw call
  3. Vertex shader преобразует вершины
  4. Fragment shader использует interpolated values
  5. GPU выводит пиксели в framebuffer

Разделение responsibilities между attributes и uniforms обеспечивает масштабируемость системы при работе с глобальными картографическими данными.