光照与后处理效果
deck.gl 的效果不是滤镜,而是渲染管线的一环。光照只影响有体积的图层, 后处理作用于最终画面,两者都会增加每帧的渲染开销。
光照只对有体积的图层生效
LightingEffect 把光源参数传进着色器。柱体、六边形、
网格模型这类有法线的几何会随光照产生明暗,散点、路径、文本不受影响。
给散点加光照不会报错,只是看不出变化。
var ambient = new deck.AmbientLight({
color: [255, 255, 255],
intensity: 1.2
});
var sun = new deck.DirectionalLight({
color: [255, 240, 214],
intensity: 1.8,
direction: [-1.2, -3, -1.6]
});
var lighting = new deck.LightingEffect({
ambientLight: ambient,
dirLight: sun
});
var hexLayer = new deck.HexagonLayer({
id: 'density-lit',
data: stations,
getPosition: function (d) { return [d.lng, d.lat]; },
radius: 800,
extruded: true,
elevationScale: 14,
material: {
ambient: 0.45,
diffuse: 0.7,
shininess: 32,
specularColor: [80, 90, 100]
}
});
new deck.Deck({
container: 'map',
initialViewState: { longitude: 116.40, latitude: 39.93, zoom: 10.5, pitch: 50 },
controller: true,
effects: [lighting],
layers: [hexLayer]
});
direction 是光线入射方向,不是光源位置。三个分量按
[x, y, z] 给出,z 为负表示从上方照下来。数值方向写反,
柱体会变成全黑或全亮。
没有法线就没有明暗。自定义 Layer 若只上传了位置属性, 即使挂了光照也不会出现立体感,需要补充法线数据。
后处理
PostProcessEffect 包装一个 luma.gl 的后处理效果,
在 deck.gl 完成主渲染后对整幅画面做一次处理。泛光、色调映射属于这一类。
import { PostProcessEffect } from '@deck.gl/core';
import { BloomEffect } from '@luma.gl/effects';
var bloom = new PostProcessEffect({
effect: new BloomEffect()
});
var deckgl = new deck.Deck({
container: 'map',
initialViewState: { longitude: 116.40, latitude: 39.93, zoom: 10.5 },
controller: true,
effects: [lighting, bloom],
layers: layers
});
效果按数组顺序执行,光照在前、后处理在后。顺序反过来时, 后处理拿不到受光后的颜色,画面会偏灰。
| 效果 | 作用对象 | 典型用途 | 开销 |
|---|---|---|---|
AmbientLight | 有法线的几何 | 整体提亮,避免暗部死黑 | 可忽略 |
DirectionalLight | 有法线的几何 | 太阳光、地形主光 | 低 |
PointLight | 有法线的几何 | 局部照明,注意数量上限 | 中 |
PostProcessEffect | 整幅画面 | 泛光、色调映射、抗锯齿 | 一次全屏 pass |
材质参数怎么调
图层的 material 决定表面如何响应光源。ambient
与 diffuse 都在 0 到 1 之间,shininess 越大高光越集中。
城市体块这类粗糙表面适合低高光、高漫反射。
// 建筑体块:哑光、几乎无高光
var matte = { ambient: 0.5, diffuse: 0.65, shininess: 4, specularColor: [60, 64, 70] };
// 金属设备:高光集中,反射偏冷
var metal = { ambient: 0.25, diffuse: 0.5, shininess: 80, specularColor: [180, 200, 220] };
hexLayer.setProps({ material: matte });
注意事项
PointLight数量增加会显著拖慢片元着色,移动端建议不超过两个。- 后处理会读取整幅画面,画布越大开销越高,高像素比设备上要相应降低渲染分辨率。
- 开启拾取时,拾取缓冲不经过后处理,命中位置可能与看到的画面略有偏差。
effects与layers一起通过setProps更新,单独替换效果不会立即生效。- 光照参数变化频繁时,考虑把亮度并入颜色访问器,避免每帧重传 uniform。
经纬志(2026)。《光照与后处理效果》。https://www.jingweizhi.com/deckgl/tutorial/effects.html(访问日期 2026-11-03)。