Visualização de sobreposição do WebGL

Amostra

Com a visualização de sobreposição do WebGL, você pode adicionar conteúdo aos mapas usando diretamente WebGL ou bibliotecas de gráficos conhecidas, como a Three.js. A visualização de sobreposição do WebGL fornece acesso direto ao mesmo contexto de renderização WebGL usado pela Plataforma Google Maps para renderizar o mapa básico vetorial. Esse uso de um contexto de renderização compartilhada oferece benefícios como a oclusão de profundidade com geometria de construção em 3D e a capacidade de sincronizar conteúdo 2D/3D com a renderização do mapa básico. Os objetos renderizados com a visualização de sobreposição do WebGL também podem ser vinculados a coordenadas de latitude/longitude. Dessa forma, eles se movem quando você arrasta, aplica zoom, movimenta ou inclina o mapa.

Requisitos

Para usar a visualização de sobreposição do WebGL, você precisa carregar o mapa usando um ID com o mapa vetorial ativado. Recomendamos ativar a inclinação e a rotação ao criar o ID do mapa para permitir o controle total da câmera 3D. Confira a visão geral para saber mais.

Adicionar a visualização de sobreposição do WebGL

Para adicionar a sobreposição ao mapa, implemente google.maps.WebGLOverlayView e, em seguida, transmita a instância do mapa usando 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);

Hooks de ciclo de vida

A visualização de sobreposição do WebGL fornece um conjunto de hooks chamados várias vezes no ciclo de vida do contexto de renderização WebGL do mapa básico vetorial. É nesses hooks de ciclo de vida que você configura, desenha e desmonta tudo o que quiser renderizar na sobreposição.

  • O onAdd() é chamado quando a sobreposição é criada. Use esse método para buscar ou criar estruturas de dados intermediárias antes de desenhar a sobreposição sem necessidade de acesso imediato ao contexto de renderização do WebGL.
  • O onContextRestored({gl}) é chamado quando o contexto de renderização está disponível. Use esse hook para inicializar ou vincular qualquer estado WebGL, como sombreadores, objetos de buffer GL e assim por diante. O onContextRestored() usa uma instância do WebGLStateOptions, que tem um único campo:
    • O gl é um handle do WebGLRenderingContext usado pelo mapa básico.
  • O onDraw({gl, transformer}) renderiza o cenário no mapa básico. Os parâmetros de onDraw() são um objeto WebGLDrawOptions, que tem dois campos:
    • O gl é um handle do WebGLRenderingContext usado pelo mapa básico.
    • O transformer fornece funções auxiliares para transformar as coordenadas do mapa em matrizes de projeção de modelo e visualização, que podem ser usadas para converter coordenadas de mapas em espaços mundiais, da câmera e da tela.
  • O onContextLost() é chamado quando o contexto de renderização é perdido por algum motivo e é onde você precisa limpar qualquer estado GL preexistente, já que ele deixa de ser necessário.
  • O onStateUpdate({gl}) atualiza o estado GL fora do loop de renderização e é invocado quando o requestStateUpdate é chamado. Ele usa uma instância de WebGLStateOptions, que tem um único campo:
    • O gl é um handle do WebGLRenderingContext usado pelo mapa básico.
  • O onRemove() é chamado quando a sobreposição é removida do mapa com o WebGLOverlayView.setMap(null), e é de onde você precisa remover todos os objetos intermediários.

Confira a seguir um exemplo de implementação básica de todos os hooks de ciclo de vida:

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);

Redefinir o estado do GL

A visualização de sobreposição do WebGL expõe o contexto de renderização do WebGL do mapa básico. Por isso, é extremamente importante redefinir o estado do GL para o original quando você termina de renderizar objetos. Se houver falha ao redefinir o estado do GL, isso provavelmente vai resultar em conflitos de estado GL, o que fará com que a renderização do mapa e de todos os objetos especificados apresente erro.

A redefinição do estado GL normalmente é processada no hook onDraw(). Por exemplo, a biblioteca Three.js oferece uma função auxiliar que apaga todas as mudanças no estado GL:

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

Se o mapa ou os objetos não forem renderizados, a probabilidade de que o estado do GL não tenha sido redefinido será bem alta.

Transformações das coordenadas

A posição de um objeto no mapa vetorial é especificada fornecendo uma combinação de coordenadas de latitude, longitude e altitude. No entanto, os gráficos 3D são especificados no espaço mundial, da câmera ou da tela. Para facilitar a transformação de coordenadas de mapa nesses espaços usados com frequência, a visualização de sobreposição do WebGL fornece a função auxiliar coordinateTransformer.fromLatLngAltitude(latLngAltitude, rotationArr, scalarArr) no hook onDraw() que usa o seguinte e retorna um Float64Array:

  • latLngAltitude: coordenadas de latitude/longitude/altitude como LatLngAltitude ou LatLngAltitudeLiteral.
  • rotationArr: Float32Array dos ângulos de rotação de Euler especificados em graus.
  • scalarArr: Float32Array dos escalares para aplicar ao eixo cardeal.

Por exemplo, o comando a seguir usa fromLatLngAltitude() para criar uma matriz de projeção de câmera na 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);

Exemplo

Confira a seguir um exemplo simples do uso da Three.js, uma biblioteca WebGL de código aberto bastante conhecida, para colocar um objeto 3D no mapa. Para conferir um tutorial completo sobre como usar a visualização de sobreposição do WebGL e criar o exemplo que aparece no topo desta página, consulte o codelab Como criar experiências de mapa aceleradas por 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);