Режим наложения в WebGL

Посмотреть пример

Вы можете добавлять контент на карты в наложениях WebGL, используя API WebGL или популярные графические библиотеки, такие как Three.js. Такие наложения обеспечивают прямой доступ к контексту визуализации WebGL, который платформа Google Карт использует для отрисовки векторной базовой карты. Общий контекст визуализации позволяет отрисовывать перекрывающиеся в глубине трехмерные здания и синхронизировать показ 2D/3D-контента с отрисовкой базовой карты. Объекты в наложениях WebGL также можно привязать к географическим координатам, чтобы закрепить их на определенном месте при перетаскивании, масштабировании, панорамировании или наклоне карты.

Требования

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

Как добавить наложение WebGL

Чтобы добавить наложение на карту, реализуйте метод google.maps.WebGLOverlayView и передайте ему свой экземпляр карты с помощью setMap:

// Create a map instance.
const map = new google.maps.Map(mapDiv, mapOptions);

// Create a WebGL Overlay View instance.
const webglOverlayView = new google.maps.WebGLOverlayView();

// Add the overlay to the map.
webglOverlayView.setMap(map);

Обработчики жизненного цикла

С наложениями WebGL можно использовать ряд обработчиков, которые вызываются в разных точках цикла отрисовки в WebGL контекста векторной базовой карты. Такие обработчики вызываются при настройке, нанесении на карту и удалении отрисовываемой в наложении информации.

  • onAdd() – вызывается при создании наложения. Используйте этот обработчик для извлечения или создания промежуточных структур данных, которые не требуют немедленного доступа к контексту визуализации WebGL, перед отрисовкой наложения.
  • onContextRestored({gl}) – вызывается, когда становится доступен контекст визуализации. Используйте этот обработчик для инициализации или привязки любого состояния WebGL (шейдеров, объектов буфера GL и т. д.). onContextRestored() принимает экземпляр класса WebGLStateOptions, содержащий одно поле:
    • gl – дескриптор WebGLRenderingContext в базовой карте.
  • onDraw({gl, transformer}) – отрисовывает сцену базовой карты. Параметры onDraw() задаются в объекте WebGLDrawOptions c двумя полями:
    • gl – дескриптор WebGLRenderingContext в базовой карте.
    • transformer – вспомогательные функции для преобразования координат карты через матрицу "модель-вид-проекция" в объекты пространства мира, камеры или экрана.
  • onContextLost() – вызывается, когда контекст визуализации потерян. Очищает все предыдущие состояния графической библиотеки, поскольку они больше не потребуются.
  • onStateUpdate({gl}) – меняет состояние графической библиотеки вне цикла отрисовки. Вызывается при вызове requestStateUpdate и принимает экземпляр класса WebGLStateOptions, содержащий одно поле:
    • gl – дескриптор WebGLRenderingContext в базовой карте.
  • onRemove() – вызывается при удалении наложения с карты с помощью метода WebGLOverlayView.setMap(null) и очищает все промежуточные объекты.

Ниже приведен пример базовой реализации всех обработчиков жизненного цикла.

const webglOverlayView = new google.maps.WebGLOverlayView();

webglOverlayView.onAdd = () => {
  // Do setup that does not require access to rendering context.
}

webglOverlayView.onContextRestored = ({gl}) => {
  // Do setup that requires access to rendering context before onDraw call.
}

webglOverlayView.onStateUpdate = ({gl}) => {
  // Do GL state setup or updates outside of the render loop.
}

webglOverlayView.onDraw = ({gl, transformer}) => {
  // Render objects.
}

webglOverlayView.onContextLost = () => {
  // Clean up pre-existing GL state.
}

webglOverlayView.onRemove = () => {
  // Remove all intermediate objects.
}

webglOverlayView.setMap(map);

Сброс состояния графической библиотеки

Наложение WebGL предоставляет контекст графической библиотеки WebGL для визуализации базовой карты. Поэтому по окончании отрисовки объектов состояние графической библиотеки важно вернуть к исходному. В противном случае это может вызвать конфликт состояний графической библиотеки и привести к сбою отрисовки карты и любых заданных на ней объектов.

Сброс состояния графической библиотеки обычно выполняется в обработчике onDraw(). Например, в Three.js предусмотрена вспомогательная функция, которая сбрасывает все изменения в состоянии библиотеки:

webglOverlayView.onDraw = ({gl, transformer}) => {
  // Specify an object to render.
  renderer.render(scene, camera);
  renderer.resetState();
}

Если ваша карта или объекты на ней не отображаются, весьма вероятно, что состояние графической библиотеки не было сброшено.

Преобразования координат

Положение объекта на векторной карте определяется комбинацией координат широты, долготы и высоты. В то же время положение объектов 3D-графики задается в пространстве мира, камеры или экрана. Чтобы упростить преобразование координат карты в координаты этих пространств, в наложении WebGL предусмотрена вспомогательная функция coordinateTransformer.fromLatLngAltitude(latLngAltitude, rotationArr, scalarArr) в обработчике onDraw(). Она принимает следующие объекты и возвращает в ответ массив Float64Array:

  • latLngAltitude – координаты широты/долготы/высоты в виде объекта LatLngAltitude или LatLngAltitudeLiteral;
  • rotationArr – массив Float32Array с углами Эйлера, задающими ориентацию в градусах;
  • scalarArr – Float32Array массив скалярных значений по главной оси.

В примере ниже метод fromLatLngAltitude() используется для создания матрицы проекций камеры в Three.js.

const camera = new THREE.PerspectiveCamera();
const matrix = coordinateTransformer.fromLatLngAltitude({
    lat: mapOptions.center.lat,
    lng: mapOptions.center.lng,
    altitude: 120,
});
camera.projectionMatrix = new THREE.Matrix4().fromArray(matrix);

Пример

Ниже приведен простой пример использования Three.js, популярной библиотеки WebGL с открытым исходным кодом, для размещения 3D-объекта на карте. Если вы хотите узнать во всех подробностях, как была создана карта, которую вы видите вверху этой страницы, выполните практическую работу по созданию карт с WebGL.

const webglOverlayView = new google.maps.WebGLOverlayView();
let scene, renderer, camera, loader;

webglOverlayView.onAdd = () => {
  // Set up the Three.js scene.
  scene = new THREE.Scene();
  camera = new THREE.PerspectiveCamera();
  const ambientLight = new THREE.AmbientLight( 0xffffff, 0.75 ); // Soft white light.
  scene.add(ambientLight);

  // Load the 3D model with GLTF Loader from Three.js.
  loader = new GLTFLoader();
  loader.load("pin.gltf");
}

webglOverlayView.onContextRestored = ({gl}) => {
  // Create the Three.js renderer, using the
  // maps's WebGL rendering context.
  renderer = new THREE.WebGLRenderer({
    canvas: gl.canvas,
    context: gl,
    ...gl.getContextAttributes(),
  });
  renderer.autoClear = false;
}

webglOverlayView.onDraw = ({gl, transformer}) => {
  // Update camera matrix to ensure the model is georeferenced correctly on the map.
  const matrix = transformer.fromLatLngAltitude({
      lat: mapOptions.center.lat,
      lng: mapOptions.center.lng,
      altitude: 120,
  });
camera.projectionMatrix = new THREE.Matrix4().fromArray(matrix);

  // Request a redraw and render the scene.
  webglOverlayView.requestRedraw();
  renderer.render(scene, camera);

  // Always reset the GL state.
  renderer.resetState();
}

// Add the overlay to the map.
webglOverlayView.setMap(map);