mirror of
https://github.com/visgl/luma.gl.git
synced 2026-01-18 14:03:42 +00:00
95 lines
3.1 KiB
Plaintext
95 lines
3.1 KiB
Plaintext
# External WebGL Contexts with MapLibre
|
|
|
|
This guide shows how to connect luma.gl to a WebGL context that is created and owned by [MapLibre GL JS](https://maplibre.org/projects/maplibre-gl-js/). It uses the `webgl2Adapter.attach` API to wrap the map's context in a `WebGLDevice` and keep a `WebGLCanvasContext` synchronized with MapLibre's canvas.
|
|
|
|
## Install dependencies
|
|
|
|
Add MapLibre GL JS alongside luma.gl:
|
|
|
|
```bash
|
|
npm install @luma.gl/webgl @luma.gl/engine maplibre-gl
|
|
```
|
|
|
|
This example uses [CARTO basemaps](https://github.com/CartoDB/basemap-styles) so you do not need an API token, but you can still supply a Mapbox token if you point MapLibre at a Mapbox-hosted style elsewhere in your application.
|
|
|
|
## Attach luma.gl to MapLibre
|
|
|
|
Create the map first so MapLibre owns the WebGL canvas, then attach the device to that context:
|
|
|
|
```typescript
|
|
import maplibregl from 'maplibre-gl'
|
|
import {Matrix4} from '@math.gl/core'
|
|
import {webgl2Adapter} from '@luma.gl/webgl'
|
|
import {Model} from '@luma.gl/engine'
|
|
|
|
const map = new maplibregl.Map({
|
|
container: 'map',
|
|
style: 'https://basemaps.cartocdn.com/gl/positron-gl-style/style.json',
|
|
antialias: true,
|
|
pitch: 60,
|
|
zoom: 12
|
|
})
|
|
|
|
map.on('load', async () => {
|
|
const webglContext = map.getCanvas().getContext('webgl2') as WebGL2RenderingContext
|
|
const device = await webgl2Adapter.attach(webglContext, {createCanvasContext: {autoResize: false}})
|
|
|
|
// Keep the WebGLCanvasContext aligned with MapLibre's drawing buffer
|
|
device.canvasContext.resize({width: webglContext.drawingBufferWidth, height: webglContext.drawingBufferHeight})
|
|
|
|
const modelMatrix = new Matrix4()
|
|
const viewProjection = new Matrix4()
|
|
|
|
const overlay = new Model(device, {
|
|
id: 'maplibre-overlay',
|
|
vs: `...`,
|
|
fs: `...`,
|
|
shaderLayout: {
|
|
attributes: [
|
|
{name: 'positions', location: 0, format: 'float32x3'}
|
|
],
|
|
bindings: [{name: 'app', type: 'uniform', location: 0}]
|
|
},
|
|
attributes: {
|
|
positions: new Float32Array([...])
|
|
},
|
|
vertexCount: 6,
|
|
bindings: {
|
|
app: /* uniform buffer */
|
|
}
|
|
})
|
|
|
|
map.addLayer({
|
|
id: 'luma-gl-overlay',
|
|
type: 'custom',
|
|
renderingMode: '3d',
|
|
render: (_, matrix) => {
|
|
viewProjection.fromArray(matrix as number[])
|
|
// Update uniforms and draw without clearing the map's buffers
|
|
const renderPass = device.beginRenderPass({clearColor: false, clearDepth: false})
|
|
overlay.draw(renderPass)
|
|
renderPass.end()
|
|
map.triggerRepaint()
|
|
}
|
|
})
|
|
})
|
|
```
|
|
|
|
## Handle map resizes
|
|
|
|
Because the context comes from MapLibre, luma.gl cannot resize it automatically. Listen for MapLibre `resize` events and keep the `WebGLCanvasContext` in sync:
|
|
|
|
```typescript
|
|
map.on('resize', () => {
|
|
const webglContext = map.getCanvas().getContext('webgl2') as WebGL2RenderingContext
|
|
device.canvasContext.resize({
|
|
width: webglContext.drawingBufferWidth,
|
|
height: webglContext.drawingBufferHeight
|
|
})
|
|
})
|
|
```
|
|
|
|
## See it in action
|
|
|
|
The revived [External WebGL Context example](/examples/api/external-webgl-context) renders a luma.gl overlay driven by MapLibre's WebGL render loop and uses the `webgl2Adapter.attach` API to keep both frameworks in sync.
|