经纬志
首页 / deck.gl / 教程

光照与后处理效果

先看结论

deck.gl 的效果不是滤镜,而是渲染管线的一环。光照只影响有体积的图层, 后处理作用于最终画面,两者都会增加每帧的渲染开销。

最后验证 2026-11-03 · deck.gl 9.0 · 难度:进阶 · 核验 2026-10-29 · 引用本文

光照只对有体积的图层生效

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