luma.gl 与 deck.gl 的关系
deck.gl 画出的每一个图层,最终都落到 luma.gl 的缓冲区、着色器与绘制调用上。 理解这一层,才能判断什么时候该写图层,什么时候该直接写 luma.gl。
两层的分工
luma.gl 是 GPU 抽象层。它把 WebGL2 与 WebGPU 的差异包起来,提供统一的设备、缓冲区、 纹理、着色器、渲染管线与绘制接口。它不关心数据是什么,也不关心地图。
deck.gl 是地理数据可视化框架。它管理图层、数据访问器、坐标系、拾取、动画过渡与视图控制, 并在内部把每个图层编译成 luma.gl 的模型与着色器。图层作者写的是「数据怎么映射」, luma.gl 负责「怎么画到 GPU 上」。
| 层次 | 负责 | 典型 API |
|---|---|---|
| 应用层 | 地图容器、交互、业务图层组合 | Deck、MapboxOverlay |
| 图层层(deck.gl) | 数据、访问器、聚合、拾取、过渡 | ScatterplotLayer、GeoJsonLayer |
| 渲染层(luma.gl) | 设备、缓冲区、着色器、管线、绘制 | Device、Buffer、Model |
| 图形接口 | WebGL2 / WebGPU | 浏览器提供 |
v9 的包结构
luma.gl 从 v9 起拆成多个包,按需引入,避免把 WebGPU 或着色器工具一起打进包体:
| 包 | 内容 | 是否必需 |
|---|---|---|
@luma.gl/core | 设备、缓冲区、纹理、着色器、渲染管线、渲染通道 | 必需 |
@luma.gl/webgl | WebGL2 适配器 webgl2Adapter | 用 WebGL 时必需 |
@luma.gl/webgpu | WebGPU 适配器 | 用 WebGPU 时必需 |
@luma.gl/shadertools | 着色器模块、着色器组装 | 用 Model 时通常需要 |
@luma.gl/engine | Model、AnimationLoop、Geometry、相机控制 | 用高层封装时必需 |
v9 不再自动注册适配器,创建设备时要显式传入,例如
adapters: [webgl2Adapter]。这是从 v8 升级时最容易漏掉的一步,
漏掉会得到「No matching device found」。
最小代码:谁在做什么
import { luma } from '@luma.gl/core';
import { webgl2Adapter } from '@luma.gl/webgl';
import { Model, AnimationLoop } from '@luma.gl/engine';
// luma.gl:创建设备与 GPU 资源
const device = await luma.createDevice({
type: 'webgl',
adapters: [webgl2Adapter],
createCanvasContext: { canvas }
});
const buffer = device.createBuffer(new Float32Array([
-0.5, -0.5, 0,
0.5, -0.5, 0,
0.0, 0.5, 0
]));
// luma.gl:把着色器、属性与绘制状态合成一个模型
const model = new Model(device, {
vs: vertexShaderSource,
fs: fragmentShaderSource,
attributes: { positions: buffer },
bufferLayout: [
{ name: 'positions', stepMode: 'vertex', format: 'float32x3' }
],
vertexCount: 3,
topology: 'triangle-list'
});
// luma.gl:动画循环里开一个渲染通道,画一次
const loop = new AnimationLoop({
device,
onRender: function (props) {
const pass = props.device.beginRenderPass({ clearColor: [0.05, 0.07, 0.1, 1] });
model.draw(pass);
pass.end();
}
});
loop.start();
这段代码里没有任何地理概念。经纬度在哪里、要画多少个点、颜色怎么映射, 都是应用层的事。deck.gl 做的正是把这些封装成图层参数。
什么时候直接用 luma.gl
- 渲染方式不是「一层数据一种图层」,例如体渲染、流场、屏幕空间特效。
- 需要精确控制渲染通道、深度、混合、实例化与多次绘制。
- 已有自己的数据结构与相机,只需要一层薄的 GPU 封装。
- 要在同一画布上混合 deck.gl 图层与自定义绘制,共用同一个设备与上下文。
什么时候不需要
只要需求能用现成图层表达,直接用 deck.gl 更省事,拾取、过渡、坐标系都已经处理好。 只是想要一个通用三维场景,three.js 的生态与文档更完整。 luma.gl 的定位是「底层但可控」,不是「更简单的 three.js」。
| 需求 | 更合适的起点 |
|---|---|
| 大规模点、线、面、聚合图层 | deck.gl |
| 三维地球、地形、3D Tiles | Cesium |
| 自定义材质、非地图场景、模型展示 | three.js |
| 自定义着色器 + 自有数据管线 | luma.gl |
先确认版本。v8 与 v9 的 API 差异很大:Program 被
RenderPipeline 取代,Geometry 变成纯 CPU 容器,
AnimationLoop 必须显式传设备。照着旧教程写,会在第一步就卡住。
经纬志(2026)。《luma.gl 与 deck.gl 的关系》。https://www.jingweizhi.com/lumagl/tutorial/luma-and-deck.html(访问日期 2026-11-03)。