Visualizzazione sovrapposta WebGL

Visualizza esempio

Con la visualizzazione sovrapposta WebGL puoi aggiungere contenuti alle mappe utilizzando direttamente WebGL o librerie grafiche famose come Three.js. La visualizzazione sovrapposta WebGL fornisce l'accesso diretto allo stesso contesto di rendering WebGL utilizzato da Google Maps Platform per eseguire il rendering della mappa base vettoriale. Questo utilizzo di un contesto di rendering condiviso offre vantaggi come l'occlusione della profondità con la geometria degli edifici in 3D e la possibilità di sincronizzare i contenuti 2D/3D con il rendering della mappa base. Gli oggetti di cui è stato eseguito il rendering con la visualizzazione sovrapposta WebGL possono anche essere collegati alle coordinate di latitudine/longitudine, in modo che si spostino quando trascini, aumenti lo zoom, esplori 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 abilitare l'inclinazione e la rotazione quando crei l'ID mappa per consentire il controllo completo della videocamera 3D. Per maggiori dettagli, consulta la panoramica.

Aggiungere la visualizzazione sovrapposta WebGL

Per aggiungere l'overlay alla mappa, implementa google.maps.WebGLOverlayView, quindi passala all'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);

Hook del ciclo di vita

La visualizzazione sovrapposta WebGL fornisce un insieme di hook che vengono chiamati in vari momenti del ciclo di vita del contesto di rendering WebGL della mappa base vettoriale. Questi hook del ciclo di vita sono il punto in cui configuri, disegni e distruggi tutto ciò di cui vuoi eseguire il rendering nell'overlay.

  • onAdd() viene chiamato 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 chiamato una volta che il contesto di rendering è disponibile. Utilizzalo per inizializzare o associare qualsiasi stato WebGL, come shader, oggetti buffer GL e così via. onContextRestored() accetta un'istanza WebGLStateOptions, che ha un solo campo:
    • gl è un handle per WebGLRenderingContext utilizzato dalla mappa base.
  • onDraw({gl, transformer}) esegue il rendering della scena sulla mappa base. I parametri di onDraw() sono un oggetto WebGLDrawOptions, che ha due campi:
    • gl è un handle per WebGLRenderingContext utilizzato dalla mappa base.
    • transformer fornisce funzioni di assistenza per trasformare le coordinate della mappa in una matrice di proiezione modello-visualizzazione, che può essere utilizzata per tradurre le coordinate della mappa in spazio mondiale, spazio della videocamera e spazio dello schermo.
  • onContextLost() viene chiamato quando il contesto di rendering viene perso per qualsiasi motivo ed è il punto in cui devi liberare spazio da qualsiasi stato GL preesistente, poiché non è più necessario.
  • onStateUpdate({gl}) aggiorna lo stato GL al di fuori del ciclo di rendering e viene richiamato quando viene chiamato requestStateUpdate. Accetta un'istanza WebGLStateOptions, che ha un solo 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 è il punto in cui devi rimuovere tutti gli oggetti intermedi.

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

Reimpostare lo stato GL

La visualizzazione sovrapposta WebGL espone il contesto di rendering WebGL della mappa 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 di stato GL, che causeranno il mancato rendering sia della mappa sia degli oggetti specificati.

La reimpostazione dello stato GL viene in genere 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 sottoposti a rendering, è 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é di altitudine. La grafica 3D, tuttavia, viene specificata nello spazio mondiale, nello spazio della videocamera o nello spazio dello schermo. Per semplificare la trasformazione delle coordinate della mappa in questi spazi di uso comune, la Visualizzazione sovrapposta WebGL fornisce la coordinateTransformer.fromLatLngAltitude(latLngAltitude, rotationArr, scalarArr) funzione helper nell'hook onDraw() che accetta quanto segue e restituisce un Float64Array:

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

Ad esempio, il seguente codice utilizza fromLatLngAltitude() per creare una matrice di proiezione della 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 utilizzo di Three.js, una libreria WebGL open source molto diffusa, per posizionare un oggetto 3D sulla mappa. Per una procedura dettagliata sull'utilizzo della visualizzazione sovrapposta WebGL per creare l'esempio che vedi in esecuzione nella parte superiore di questa pagina, prova il codelab Creare esperienze di mappe accelerate da 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);