Aggiungere un livello WebGL personalizzato a una mappa

L'SDK Web di Mappe di Azure supporta la creazione di livelli personalizzati tramite WebGL. WebGL si basa su OpenGL ES e consente il rendering della grafica 2D e 3D nei Web browser.

Usando WebGL, è possibile creare grafica interattiva ad alte prestazioni che eseguono il rendering nel browser in tempo reale che supporta scenari come simulazioni, visualizzazione dei dati, animazioni e modellazione 3D.

Gli sviluppatori possono accedere al contesto WebGL della mappa durante il rendering e usare livelli WebGL personalizzati per l'integrazione con altre librerie, ad esempio three.js e deck.gl per fornire contenuti arricchiti e interattivi sulla mappa.

Aggiungere un livello WebGL

Prima di poter aggiungere un livello WebGL a una mappa, è necessario disporre di un oggetto che implementa l'interfaccia WebGLRenderer . Prima di tutto, creare un livello WebGL fornendo un id oggetto e renderer al costruttore, quindi aggiungere il livello alla mappa per eseguirne il rendering.

Il codice di esempio seguente illustra come aggiungere un livello WebGL a una mappa:

var myRenderer = {
    /**
     * Either "2d" or "3d". Defaults to "2d".
     * - "3d" to use the depth buffer and share it with other layers
     * - "2d" to add a layer with no depth. If you need to use the depth buffer for a "2d"
     *   layer you must use an offscreen framebuffer and the prerender method.
     */
    renderingMode: "2d",

    /**
     * Optional method called when the layer has been added to the Map.
     * This gives the layer a chance to initialize gl resources and register event listeners.
     * @param map The Map this custom layer was just added to.
     * @param gl The gl context for the map.
     */
    onAdd: function (map, gl) {},

    /**
     * Optional method called when the layer has been removed from the Map.
     * This gives the layer a chance to clean up gl resources and event listeners.
     * @param map The Map this custom layer was just added to.
     * @param gl The gl context for the map.
     */
    onRemove: function (map, gl) {},

    /**
     * Optional method called during a render frame to allow a layer to prepare resources
     * or render into a texture.
     *
     * The layer cannot make any assumptions about the current GL state and must bind a framebuffer before rendering.
     *
     * @param gl The map's gl context.
     * @param matrix The map's camera matrix.
     */
    prerender: function (gl, matrix) {},

    /**
     * Required. Called during a render frame allowing the layer to draw into the GL context.
     *
     * The layer can assume blending and depth state is set to allow the layer to
     * properly blend and clip other layers. The layer cannot make any other 
     * assumptions about the current GL state.
     *
     * If the layer needs to render to a texture, it should implement the prerender
     * method to do this and only use the render method for drawing directly into the
     * main framebuffer.
     *
     * The blend function is set to gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA).
     * This expects colors to be provided in premultiplied alpha form where the r, g and b
     * values are already multiplied by the a value. If you are unable to provide colors in
     * premultiplied form you may want to change the blend function to
     * gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA).
     *
     * @param gl The map's gl context.
     * @param matrix The map's camera matrix.
     */
    render: function (gl, matrix) {}
};
 
//Add the layer to the map.
map.layers.add(new atlas.layer.WebGLLayer("layerId", { renderer: myRenderer }));

Nota

La WebGLLayer classe supporta le minZoomopzioni di livello , maxZoome visible .

//Add the layer to the map with layer options. 
map.layers.add(new atlas.layer.WebGLLayer("layerId", 
    { 
        renderer: myRenderer, 
        minZoom: 10, 
        maxZoom: 22, 
        visible: true
    }
));

Questo esempio esegue il rendering di un triangolo sulla mappa usando un livello WebGL.

A screenshot showing a triangle rendered on a map, using a WebGL layer.

Per un esempio completamente funzionale con il codice sorgente, vedere Livello WebGL 2D semplice negli esempi di Mappe di Azure.

La matrice della fotocamera della mappa viene usata per proiettare un punto mercatore sferico alle gl coordinate. Il punto mercator [0, 0] rappresenta l'angolo superiore sinistro del mondo Mercator e [1, 1] rappresenta l'angolo inferiore destro. Quando renderingMode è "3d", la coordinata z è conforme. Il rendering di una casella con lunghezze x, y e z identiche in unità mercator viene eseguito come cubo.

La MercatorPoint classe dispone fromPositiondi metodi statici , fromPositionse toFloat32Array che possono essere usati per convertire una posizione geospaziale in un punto mercatore. Analogamente, i toPosition metodi e toPositions possono essere usati per proiettare un Mercator che punta a una posizione.

Eseguire il rendering di un modello 3D

Usare un livello WebGL per eseguire il rendering di modelli 3D. L'esempio seguente illustra come caricare un file glTF ed eseguirne il rendering sulla mappa usando three.js.

È necessario aggiungere i file di script seguenti.

<script src="https://unpkg.com/three@latest/build/three.min.js"></script>
<script src="https://unpkg.com/three@latest/examples/js/loaders/GLTFLoader.js"></script>

Questo esempio esegue il rendering di un pappagallo 3D animato sulla mappa.

A screenshot showing an animated 3D parrot on the map.

Per un esempio completamente funzionale con il codice sorgente, vedere Tre livelli WebGL personalizzati negli esempi di Mappe di Azure.

La onAdd funzione carica un .glb file in memoria e crea un'istanza di tre oggetti js, ad esempio Fotocamera, Scene, Light e .THREE.WebGLRenderer

La render funzione calcola la matrice di proiezione della fotocamera ed esegue il rendering del modello nella scena.

Suggerimento

  • Per avere un'animazione continua e fluida, puoi attivare il ripaint di un singolo fotogramma chiamando map.triggerRepaint() nella render funzione .
  • Per abilitare l'anti-aliasing è sufficiente impostare su antialias true come una delle opzioni di stile durante la creazione della mappa.

Eseguire il rendering di un modello 3D usando babylon.js

Babylon.js è uno dei principali motori di grafica basati su WebGL al mondo. L'esempio seguente illustra come caricare un file GLTF ed eseguirne il rendering sulla mappa usando babylon.js.

È necessario aggiungere i file di script seguenti.

<script src="https://cdn.babylonjs.com/babylon.js"></script> 
<script src="https://cdn.babylonjs.com/loaders/babylonjs.loaders.min.js"></script> 

Questo esempio esegue il rendering di una torre satellite sulla mappa.

La onAdd funzione crea un'istanza di un motore BABYLON e di una scena. Carica quindi un .gltf file usando BABYLON. SceneLoader.

La render funzione calcola la matrice di proiezione della fotocamera ed esegue il rendering del modello nella scena.

A screenshot showing an example of rendering a 3D model using babylon.js.

Per un esempio completamente funzionale con il codice sorgente, vedere Livello WebGL personalizzato di Babilonia negli esempi di Mappe di Azure.

Eseguire il rendering di un livello deck.gl

È possibile usare un livello WebGL per eseguire il rendering dei livelli dalla libreria di deck.gl . L'esempio seguente illustra la visualizzazione dei dati del flusso di migrazione delle persone nel Stati Uniti dalla contea alla contea entro un determinato intervallo di tempo.

È necessario aggiungere il file di script seguente.

<script src="https://unpkg.com/deck.gl@latest/dist.min.js"></script> 

Definire una classe di livello che estende atlas.layer.WebGLLayer.

class DeckGLLayer extends atlas.layer.WebGLLayer { 

    constructor(options) { 
        super(options.id); 

        //Create an instance of deck.gl layer 
        this._mbLayer = new deck.MapboxLayer(options); 

        //Create a renderer 
        const deckGLRenderer = { 
            renderingMode: "3d", 
            onAdd: (map, gl) => { 
               this._mbLayer.onAdd?.(map["map"], gl); 
            }, 
            onRemove: (map, gl) => { 
                this._mbLayer.onRemove?.(map["map"], gl); 
            }, 
            prerender: (gl, matrix) => { 
                this._mbLayer.prerender?.(gl, matrix); 
            }, 
            render: (gl, matrix) => { 
                this._mbLayer.render(gl, matrix); 
            } 
        }; 
        this.setOptions({ renderer: deckGLRenderer }); 
    } 
} 

In questo esempio viene eseguito il rendering di un oggetto google a livello di arco della libreria deck.gl .

A screenshot showing an arc-layer from the Deck G L library.

Per un esempio completamente funzionale con il codice sorgente, vedere Deck GL custom WebGL layer in the Mappe di Azure Samples (Esempi di Mappe di Azure).

Passaggi successivi

Per altre informazioni sulle classi e sui metodi usati in questo articolo, vedere: