Visualizzazione overlay WebGL

Visualizza esempio

Con la visualizzazione sovrapposta di WebGL puoi aggiungere contenuti alle mappe utilizzando direttamente WebGL o le librerie di grafica più diffuse come Three.js. La visualizzazione sovrapposta di WebGL fornisce l'accesso diretto allo stesso contesto di rendering WebGL utilizzato da Google Maps Platform per eseguire il rendering della mappa base di base. L'utilizzo di un contesto di rendering condiviso offre vantaggi quali l'occultamento in profondità con la geometria degli edifici 3D e la possibilità di sincronizzare contenuti 2D/3D con il rendering della mappa di base. Gli oggetti visualizzati con la visualizzazione sovrapposta di WebGL possono essere associati anche alle coordinate di latitudine/longitudine, in modo che si spostino quando trascini, esegui lo zoom, la panoramica o inclina la mappa.

Requisiti

Per utilizzare la visualizzazione sovrapposta di WebGL, devi caricare la mappa utilizzando un ID mappa con la mappa vettoriale attivata. 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 visualizzazione overlay WebGL

Per aggiungere l'overlay alla mappa, implementa google.maps.WebGLOverlayView e poi passa l'istanza di 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 sovrapposta di WebGL fornisce un insieme di hook che vengono chiamati in vari momenti del ciclo di vita del contesto di rendering di WebGL della mappa base. Questi hook di ciclo di vita sono il punto in cui configuri, disegna e abbatti gli elementi che vuoi mostrare nell'overlay.

  • onAdd() viene richiamato quando viene creato l'overlay. Utilizzalo per recuperare o creare strutture di dati intermedie prima che venga disegnato l'overlay che non richiedono l'accesso immediato al contesto di rendering WebGL.
  • onContextRestored({gl}) viene richiamato quando il contesto di rendering è disponibile. Usalo per inizializzare o associare qualsiasi stato WebGL come ombreggiatori, oggetti buffer GL e così via. onContextRestored() accetta un'istanza WebGLStateOptions, che ha un singolo campo:
    • gl è un handle del WebGLRenderingContext utilizzato dalla mappa di base.
  • onDraw({gl, transformer}) mostra la scena sulla mappa base. I parametri per onDraw() sono un oggetto WebGLDrawOptions, che ha due campi:
    • gl è un handle del WebGLRenderingContext utilizzato dalla mappa di base.
    • transformer offre funzioni helper per la trasformazione dalle coordinate della mappa alla matrice della visualizzazione modello-proiezione, che può essere utilizzata per tradurre le coordinate della mappa nello spazio mondiale, nello spazio della fotocamera e nello spazio dello schermo.
  • Il comando onContextLost() viene richiamato quando il contesto di rendering viene perso per qualsiasi motivo ed è il punto in cui devi ripulire 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 richiamato requestStateUpdate. Prende un'istanza WebGLStateOptions, che ha un singolo campo:
    • gl è un handle del WebGLRenderingContext utilizzato dalla mappa di base.
  • onRemove() viene richiamato quando l'overlay viene rimosso dalla mappa con WebGLOverlayView.setMap(null) ed è il punto in cui 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 dello stato GL

La visualizzazione sovrapposta di WebGL espone il contesto di rendering WebGL della mappa di base. Per questo motivo, è estremamente importante reimpostare lo stato GL al suo stato originale al termine del rendering degli oggetti. Se non reimposti lo stato GL, è probabile che si verifichino conflitti a livello di GL, il che causerà il malfunzionamento della visualizzazione della mappa e di tutti gli oggetti specificati.

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

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

Se il rendering della mappa o dei tuoi oggetti non riesce, è molto probabile che lo stato GL non sia stato reimpostato.

Trasformazioni delle coordinate

La posizione di un oggetto sulla mappa vettoriale viene specificata fornendo una combinazione di coordinate di latitudine e longitudine, nonché altitudine. Le grafiche 3D, tuttavia, sono specificate nello spazio mondiale, nello spazio della fotocamera o nello schermo. Per semplificare la trasformazione delle coordinate della mappa in questi spazi più utilizzati, la visualizzazione sovrapposta di WebGL fornisce la funzione helper coordinateTransformer.fromLatLngAltitude(latLngAltitude, rotationArr, scalarArr) nell'hook onDraw() che prende quanto segue e restituisce un Float64Array:

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

Ad esempio, quanto segue utilizza fromLatLngAltitude() per creare una matrice di proiezione videocamera 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 come utilizzare Three.js, una popolare libreria WebGL open source, per posizionare un oggetto 3D sulla mappa. Per una procedura dettagliata completa sull'utilizzo della visualizzazione sovrapposta di WebGL per creare l'esempio che vedi in esecuzione in questa pagina, prova a consultare il codelab su come creare esperienze con le mappe WebGL accelerate.

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