GL контекст

В основе рендеринга карты лежит WebGL-контекст, создаваемый поверх HTML5 <canvas> элемента. Именно этот контекст обеспечивает аппаратное ускорение, управление GPU-пайплайном и отрисовку всех слоёв карты: тайлов, векторных данных, растровых текстур, 3D-объектов и пользовательских визуальных элементов.


Архитектура WebGL контекста

Mapbox GL JS использует WebGL как низкоуровневый слой рендеринга. После инициализации карты создаётся:

  • HTMLCanvasElement
  • WebGLRenderingContext (или WebGL2RenderingContext, если доступно)
  • внутренний объект рендерера (Painter)
  • графический контекст сцены (Scene Graph)

Контекст связывается с canvas один раз и становится центральной точкой всех графических операций.

Ключевая особенность заключается в том, что библиотека полностью управляет состоянием WebGL-контекста, минимизируя прямое вмешательство пользователя.


Получение доступа к GL контексту

Внутренний WebGL-контекст доступен через низкоуровневые объекты карты:

  • map.painter.context.gl
  • map.painter.gl
  • map._context.gl (внутренний API, нестабильный)

Прямой доступ используется редко, так как нарушает инкапсуляцию рендерера, однако он необходим для:

  • реализации custom layer
  • интеграции сторонних WebGL библиотек
  • низкоуровневой оптимизации
  • отладки GPU-пайплайна

Жизненный цикл WebGL контекста

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

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

При потере контекста браузер генерирует событие webglcontextlost.

Mapbox GL JS обрабатывает этот сценарий автоматически:

  1. фиксируется событие потери контекста
  2. блокируется рендеринг
  3. инициируется восстановление состояния
  4. пересоздаются буферы, шейдеры и текстуры
  5. сцена перерисовывается

Состояние GL контекста и управление ресурсами

WebGL-контекст в Mapbox GL JS управляет несколькими типами ресурсов:

  • Vertex Buffer Objects (VBO)
  • Index Buffer Objects (IBO)
  • Textures
  • Framebuffer objects (FBO)
  • Shader programs

Каждый слой карты соответствует набору GPU-ресурсов. При изменении данных происходит:

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

Ключевая оптимизация заключается в переиспользовании ресурсов между кадрами, что снижает нагрузку на GPU.


WebGL state machine и особенности управления состоянием

WebGL представляет собой state machine, где любое изменение состояния влияет на последующие операции рендеринга. Mapbox GL JS абстрагирует это через Painter, который:

  • централизует управление состоянием
  • минимизирует лишние вызовы gl.enable / gl.disable
  • кеширует активные программы шейдеров
  • контролирует binding текстур и буферов

Типичные состояния, которыми управляет рендерер:

  • активный shader program
  • текущий framebuffer
  • blending режимы
  • depth test и stencil test
  • viewport параметры

Custom Layer и интеграция с GL контекстом

Custom Layer предоставляет доступ к WebGL-контексту через API:

  • onAdd(map, gl)
  • render(gl, matrix)

Внутри render передаётся активный GL-контекст, синхронизированный с состоянием Mapbox GL JS.

Особенности работы:

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

Типичный поток работы:

  1. получение текущего gl контекста
  2. создание собственных буферов
  3. привязка шейдеров
  4. использование matrix (projection * view)
  5. отрисовка поверх карты

Синхронизация матриц и GL контекста

GL контекст работает в тесной связке с матрицами трансформации:

  • projection matrix
  • view matrix
  • model matrix (для объектов custom layer)

Mapbox GL JS предоставляет комбинированную матрицу, которая уже учитывает:

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

Итоговая матрица используется напрямую в vertex shader:

  • преобразование координат тайлов
  • перевод географических координат в clip space
  • корректная перспектива 3D сцены

Контекст и производительность

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

  • количеством draw calls
  • размером батчей геометрии
  • количеством активных текстур
  • частотой пересборки буферов

Основные оптимизации:

  • batching однотипных объектов
  • атлас текстур вместо множества отдельных изображений
  • reuse buffer objects
  • минимизация state changes
  • использование instancing (при поддержке WebGL2)

Потеря и восстановление контекста

Сценарий потери контекста критичен для стабильности рендера. При возникновении webglcontextlost:

  • GPU ресурсы становятся недоступны
  • все WebGL объекты считаются уничтоженными
  • рендеринг останавливается

Восстановление (webglcontextrestored) включает:

  • пересоздание shader programs
  • повторную загрузку текстур
  • восстановление vertex buffers
  • синхронизацию состояния слоёв

Важно учитывать, что восстановление не гарантирует сохранение промежуточного состояния GPU, поэтому состояние сцены пересобирается из исходных данных.


Ограничения GL контекста в браузерной среде

WebGL в контексте Mapbox GL JS подчиняется ограничениям браузера:

  • ограниченное количество текстурных юнитов
  • лимит на размер буферов
  • различия WebGL1 и WebGL2
  • вариативность драйверов GPU

Типичные ограничения:

  • max texture size
  • max vertex attributes
  • max combined texture units

Эти параметры определяют максимальную сложность сцены.


Изоляция GL состояния внутри рендерера

Mapbox GL JS строго изолирует GL состояние от внешнего кода. Это достигается:

  • централизованным state manager
  • контролем всех bind/unbind операций
  • кешированием текущего состояния контекста
  • предотвращением конфликтов между слоями

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


WebGL контекст и тайловая система

Тайловая система напрямую зависит от GL контекста:

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

GL контекст обеспечивает:

  • трансформацию тайлов в экранное пространство
  • кэширование загруженных данных
  • отбрасывание невидимых областей (culling)

Роль GL контекста в 3D рендеринге

При использовании наклона и вращения карты GL контекст переходит в режим полноценной 3D сцены:

  • включается depth testing
  • используется перспективная проекция
  • активируется z-buffer
  • применяется освещение (в ограниченном виде)

Это позволяет отображать:

  • здания с высотой
  • extruded polygons
  • 3D terrain (в зависимости от источника данных)

GL контекст становится полноценным 3D движком, встроенным в карту.