Механизм пользовательских слоёв основан на интерфейсе
CustomLayerInterface, который позволяет внедрять
произвольную WebGL-логику в графический конвейер рендеринга карты. Слой
интегрируется непосредственно в сцену, управляемую движком Mapbox, и
получает доступ к уже инициализированному WebGL-контексту.
Ключевая особенность подхода заключается в совместном использовании
контекста WebGL. Карта не создаёт отдельный gl для каждого
слоя; вместо этого все кастомные слои работают в одном контексте с
базовыми тайлами, линиями, полигонами и символами. Это исключает
дорогостоящие переключения контекста и позволяет синхронизировать
отрисовку с внутренним рендер-циклом.
Структура слоя описывается объектом с обязательными полями:
id — уникальный идентификатор слояtype — всегда "custom"renderingMode — "2d" или
"3d"onAdd(map, gl) — инициализация ресурсовrender(gl, matrix) — основной рендеринг кадраДополнительно может использоваться prerender (в
некоторых версиях или расширенных реализациях) для подготовки состояния
перед основным проходом.
onAddМетод onAdd(map, gl) вызывается один раз при добавлении
слоя в стиль карты. В этот момент доступны:
Типичный сценарий инициализации включает:
Важно учитывать, что контекст уже управляется системой Mapbox, поэтому изменение глобальных состояний WebGL (например, отключение depth test или изменение blend mode) должно выполняться аккуратно и восстанавливаться после использования.
renderМетод render(gl, matrix) вызывается на каждом кадре при
необходимости перерисовки слоя. Входные данные:
gl — активный WebGLRenderingContextmatrix — комбинированная матрица проекции и камерыМатрица используется для преобразования координат из географического пространства в clip space. Обычно она умножается на позицию вершины в вершинном шейдере:
gl_Position = u_matrix * vec4(a_position, 1.0);
Слой должен самостоятельно управлять:
bindBuffer)useProgram)drawArrays или drawElementsВнутренняя система координат Mapbox основана на проекции Mercator. В кастомных слоях не используется прямое преобразование широты и долготы в WebGL. Вместо этого передаются уже преобразованные координаты в пространстве tile/mercator.
Матрица matrix, передаваемая в render,
учитывает:
Это позволяет строить визуализации, которые автоматически синхронизируются с камерой без ручного пересчёта геометрии.
Поскольку все кастомные слои разделяют один контекст, критично соблюдение правил изоляции состояния.
Типичные ошибки:
blendFunc без восстановленияdepthMask(false)Рекомендуется сохранять состояние перед изменениями:
const prevProgram = gl.getParameter(gl.CURRENT_PROGRAM);
const prevArrayBuffer = gl.getParameter(gl.ARRAY_BUFFER_BINDING);
После завершения рендера состояние возвращается к исходному.
Кастомные слои почти всегда используют собственные GLSL-шейдеры.
Основная задача — преобразование координат:
attribute vec3 a_position;
uniform mat4 u_matrix;
void main() {
gl_Position = u_matrix * vec4(a_position, 1.0);
}
Отвечает за цвет и визуальные эффекты:
precision mediump float;
uniform vec4 u_color;
void main() {
gl_FragColor = u_color;
}
В более сложных случаях добавляются:
Параметр renderingMode определяет поведение слоя в
пайплайне.
Используется для:
Используется для:
Кастомные слои оказывают прямое влияние на FPS, так как выполняются в основном рендер-цикле.
Критические факторы:
Оптимизация часто сводится к:
Особенно важно избегать пересоздания WebGL-ресурсов внутри
render, так как это приводит к фрагментации GPU-памяти и
деградации производительности.
Кастомный слой не обязан быть изолированным. Он может использовать данные из:
Типичный подход — синхронизация слоя с
map.on('data', ...), где обновляются буферы при изменении
источников.
Для корректного поведения слоя необходимо учитывать параметры камеры:
Эти значения косвенно уже включены в matrix, однако
иногда требуется дополнительная логика:
Кастомные слои тесно связаны с событиями карты:
zoom)move)rotate)load)Слой может реагировать на эти события и пересчитывать внутреннее состояние. При этом рендер остаётся синхронным с внутренним циклом Mapbox GL.
Архитектура накладывает ряд ограничений:
Эти ограничения компенсируются высокой степенью интеграции с картографическим движком и автоматическим управлением камерой и проекциями.