Visualizzazione overlay WebGL

Visualizza esempio

Con la visualizzazione sovrapposta WebGL puoi aggiungere contenuti alle mappe utilizzando direttamente WebGL o le librerie grafiche più diffuse come Three.js. La visualizzazione overlay di WebGL offre accesso diretto allo stesso contesto di rendering WebGL utilizzato da Google Maps Platform per eseguire il rendering della mappa base vettoriale. Questo uso di un contesto di rendering condiviso offre vantaggi come l'occlusione della profondità con la geometria di edifici 3D e la possibilità di sincronizzare contenuti 2D/3D con il rendering della mappa base. Gli oggetti visualizzati con la vista sovrapposta WebGL possono anche essere collegati a coordinate di latitudine e longitudine, in modo che si spostino quando trascini, esegui lo zoom, fai una panoramica o inclini la mappa.

Requisiti

Per utilizzare la visualizzazione sovrapposta WebGL, devi caricare la mappa utilizzando un ID mappa con la mappa vettoriale abilitata. Ti consigliamo vivamente di attivare l'inclinazione e la rotazione quando crei l'ID mappa, per consentire il controllo completo della fotocamera 3D. Consulta la panoramica per i dettagli.

Aggiungi vista sovrapposta WebGL

Per aggiungere l'overlay alla mappa, implementa google.maps.WebGLOverlayView, poi trasmetti l'istanza della mappa utilizzando 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);

Ganci per ciclo di vita

La visualizzazione overlay WebGL fornisce un insieme di hook che vengono chiamati in vari momenti nel ciclo di vita del contesto di rendering WebGL della mappa base vettoriale. Questi hook del ciclo di vita ti consentono di configurare, disegnare e rimuovere tutto ciò che vuoi che venga visualizzato nell'overlay.

  • La voce onAdd() viene richiamata al momento della creazione dell'overlay. Utilizzalo per recuperare o creare strutture di dati intermedi prima di disegnare l'overlay che non richiedono l'accesso immediato al contesto di rendering WebGL.
  • onContextRestored({gl}) viene chiamato quando il contesto di rendering è disponibile. Utilizzalo per inizializzare o associare qualsiasi stato WebGL come shabbyer, oggetti buffer GL e così via. onContextRestored() prende un'istanza WebGLStateOptions, che ha un singolo campo:
    • gl è un handle per WebGLRenderingContext utilizzato dalla mappa base.
  • onDraw({gl, transformer}) esegue il rendering della scena sulla mappa base. I parametri per onDraw() è un oggetto WebGLDrawOptions, che ha due campi:
    • gl è un handle per WebGLRenderingContext utilizzato dalla mappa base.
    • transformer fornisce funzioni helper per trasformare le coordinate della mappa in matrice di proiezione-visualizzazione del modello. Queste funzioni possono essere utilizzate per tradurre le coordinate della mappa nello spazio mondiale, nello spazio della fotocamera e nello spazio dello schermo.
  • onContextLost() viene chiamato quando il contesto di rendering va perso per qualsiasi motivo ed è qui che occorre pulire qualsiasi stato GL preesistente, poiché non è più necessario.
  • onStateUpdate({gl}) aggiorna lo stato GL al di fuori del loop di rendering e viene richiamato quando viene chiamato requestStateUpdate. Richiede un'istanza WebGLStateOptions, che ha un singolo campo:
    • gl è un handle per WebGLRenderingContext utilizzato dalla mappa base.
  • onRemove() viene chiamato quando l'overlay viene rimosso dalla mappa con WebGLOverlayView.setMap(null) ed è qui che devi rimuovere tutti gli oggetti intermedi.

Ad esempio, di seguito è riportata un'implementazione di base di tutti gli hook del ciclo di vita:

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

Reimpostazione stato GL

La visualizzazione sovrapposta WebGL mostra il contesto del rendering WebGL della mappa base. Per questo motivo, è estremamente importante reimpostare lo stato GL sul suo stato originale quando hai completato il rendering degli oggetti. La mancata reimpostazione dello stato GL potrebbe causare conflitti di stato GL, che causano l'errore di rendering della mappa e degli oggetti specificati.

La reimpostazione dello stato GL viene generalmente gestita nell'hook onDraw(). Ad esempio, Three.js fornisce una funzione helper che cancella tutte le modifiche allo stato GL:

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

Se la mappa o gli oggetti non vengono visualizzati, è molto probabile che lo stato GL non sia stato reimpostato.

Coordina le trasformazioni

La posizione di un oggetto sulla mappa vettoriale viene specificata fornendo una combinazione di coordinate di latitudine e longitudine, oltre che di altitudine. Tuttavia, le immagini 3D vengono specificate nello spazio mondiale, nello spazio della videocamera o nello spazio dello schermo. Per semplificare la trasformazione delle coordinate della mappa in spazi di uso comune, la vista sovrapposta WebGL offre la funzione helper coordinateTransformer.fromLatLngAltitude(latLngAltitude, rotationArr, scalarArr) nell'hook onDraw() che riceve quanto segue e restituisce Float64Array:

  • latLngAltitude: coordinate di latitudine/longitudine/altitudine nel formato LatLngAltitude o LatLngAltitudeLiteral.
  • rotationArr: Float32Array degli angoli di rotazione specificati in gradi.
  • scalarArr: Float32Array di scalari da applicare all'asse cardinale.

Ad esempio, in questo codice viene utilizzato fromLatLngAltitude() per creare una matrice di proiezione della fotocamera in 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);

Esempio

Di seguito è riportato un semplice esempio di utilizzo di Three.js, una popolare libreria WebGL open source, per posizionare un oggetto 3D sulla mappa. Per una procedura dettagliata completa sull'utilizzo della vista sovrapposta WebGL per creare l'esempio mostrato nella parte superiore di questa pagina, prova il codelab per la creazione di esperienze di mappa con accelerazione 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);