Включение 3D terrain

Mapbox GL JS поддерживает рендеринг трёхмерного рельефа за счёт использования DEM (Digital Elevation Model) и встроенного механизма преобразования растровых высотных данных в геометрию WebGL-сцены. 3D terrain в этой системе не является отдельной геометрической моделью — это деформация базового земного слоя с применением высотной карты, синхронизированной с камерой и системой тайлов.

Основой 3D-рельефа выступает источник типа raster-dem. В экосистеме Mapbox это чаще всего один из тайлсетов, содержащих данные высот в виде RGB-кодированных значений.

Ключевые характеристики DEM:

  • хранение высоты в виде закодированных значений каналов изображения;
  • тайловая структура (z/x/y);
  • совместимость с terrain-движком WebGL;
  • поддержка интерполяции между тайлами.

Добавление источника выполняется через addSource:

map.addSource('mapbox-dem', {
  type: 'raster-dem',
  url: 'mapbox://mapbox.terrain-rgb',
  tileSize: 512,
  maxzoom: 14
});

Параметр tileSize критичен для качества визуализации: меньшие значения повышают детализацию ценой производительности, большие — ускоряют отрисовку, но сглаживают рельеф.

Активация 3D terrain через setTerrain

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

map.setTerrain({
  source: 'mapbox-dem',
  exaggeration: 1.5
});

Параметр exaggeration управляет вертикальным масштабированием:

  • 1.0 — физически корректная высота;
  • > 1.0 — усиление рельефа;
  • < 1.0 — сглаживание.

Внутренне Mapbox GL JS трансформирует вершинную сетку тайлов, поднимая каждую точку на высоту, полученную из DEM-слоя.

Роль камеры и перспективной проекции

3D terrain становится визуально корректным только при использовании перспективной камеры. В Mapbox GL JS камера определяется через параметры центра, наклона и вращения.

map.setPitch(60);
map.setBearing(-20);
  • pitch управляет углом наклона камеры относительно поверхности;
  • bearing задаёт поворот сцены вокруг вертикальной оси.

При увеличении pitch активируется перспектива, при которой горизонт начинает «уходить вдаль», а рельеф приобретает объём.

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

Рендеринг 3D terrain опирается на WebGL-буферы и фрагментацию тайлов. Производительность зависит от нескольких факторов:

  • плотность DEM-тайлов;
  • максимальный zoom источника;
  • уровень детализации в текущем viewport;
  • количество одновременно активных слоёв.

Для стабильной работы используется ограничение:

map.addSource('mapbox-dem', {
  type: 'raster-dem',
  url: 'mapbox://mapbox.terrain-rgb',
  tileSize: 512,
  maxzoom: 12
});

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

Взаимодействие terrain с растровыми и векторными слоями

После включения terrain все слои карты начинают «обтекать» рельеф. Это достигается за счёт пересчёта координат вершин в зависимости от высоты DEM.

Особенно важно поведение следующих типов слоёв:

  • fill — деформируется по поверхности;
  • line — повторяет контур рельефа;
  • symbol — сохраняет привязку к географическим координатам;
  • hillshade — усиливает визуальную читаемость рельефа.

Пример добавления слоя поверх terrain:

map.addLayer({
  id: 'terrain-layer',
  type: 'fill',
  source: 'contours',
  paint: {
    'fill-color': '#4a7',
    'fill-opacity': 0.5
  }
});

Использование sky layer для визуального объёма

Для корректного восприятия глубины сцены применяется слой неба (sky). Он создаёт градиентный фон, реагирующий на угол камеры.

map.addLayer({
  id: 'sky',
  type: 'sky',
  paint: {
    'sky-type': 'atmosphere',
    'sky-atmosphere-sun-intensity': 10
  }
});

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

Комбинация terrain и источников освещения

3D terrain визуально усиливается при использовании световых эффектов. Mapbox GL JS моделирует освещение через направление «виртуального солнца».

Параметры освещения влияют на:

  • контраст склонов;
  • выраженность теней;
  • читаемость мелких форм рельефа.

В сочетании с terrain это создаёт динамическую картину, зависящую от угла обзора.

Работа с exaggeration в динамике

Параметр exaggeration может изменяться во время работы карты, что позволяет анимировать рельеф:

map.setTerrain({ source: 'mapbox-dem', exaggeration: 2.0 });

setTimeout(() => {
  map.setTerrain({ source: 'mapbox-dem', exaggeration: 1.0 });
}, 3000);

При изменении значения WebGL пересчитывает матрицы высот без перезагрузки тайлов.

Взаимодействие с 3D зданиями

Хотя terrain отвечает за рельеф, векторные extrusions зданий работают поверх него. При одновременном использовании:

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

Важно учитывать порядок слоёв и корректную настройку fill-extrusion-height, чтобы избежать визуальных артефактов на пересечении с рельефом.

Ограничения и особенности рендеринга

3D terrain в Mapbox GL JS имеет архитектурные ограничения:

  • невозможность полной физической симуляции поверхности;
  • ограниченная точность DEM на низких zoom-уровнях;
  • зависимость качества от исходного тайлсета;
  • повышенная нагрузка на GPU при высоком pitch и zoom.

При недостатке ресурсов происходит деградация качества тайлов, выражающаяся в сглаживании высот.

Структура рендеринга terrain в WebGL

На уровне WebGL процесс включает:

  1. загрузку DEM-тайлов;
  2. декодирование RGB в высоты;
  3. генерацию mesh-сетки;
  4. деформацию вершин в vertex shader;
  5. текстурирование поверхности;
  6. наложение слоёв карты.

Vertex shader получает высоту как дополнительную координату Z, формируя трёхмерную поверхность без создания отдельных 3D-моделей.

Практическая конфигурация сцены terrain

Полная минимальная конфигурация включает:

map.on('load', () => {
  map.addSource('mapbox-dem', {
    type: 'raster-dem',
    url: 'mapbox://mapbox.terrain-rgb',
    tileSize: 512,
    maxzoom: 14
  });

  map.setTerrain({
    source: 'mapbox-dem',
    exaggeration: 1.3
  });

  map.addLayer({
    id: 'sky',
    type: 'sky',
    paint: {
      'sky-type': 'atmosphere'
    }
  });

  map.setPitch(65);
});

Такая конфигурация активирует связку DEM + terrain + sky, формируя полноценную 3D-сцену с непрерывной поверхностью и перспективной камерой.