mcpField
M
maplibre-terrain-rendering

maplibre-terrain-rendering

github.com/maplibre设计与 UI155207 次安装今天更新
代码仓库

关于 maplibre-terrain-rendering

为 MapLibre 开发者介绍 DEM 地形的渲染方式,涵盖 hillshade、高程着色、等高线、3D 地形与天空设置,并说明性能注意事项。

主要功能

  1. 01配置 hillshade 阴影效果
  2. 02按高程动态着色
  3. 03通过 maplibre-contour 生成等高线
  4. 04设置 3D 地形、相机与天空
  5. 05了解地形渲染的性能成本

适用场景

  1. 01改善地形阴影的对比效果
  2. 02制作按高度着色的地图
  3. 03在运行时绘制等高线
  4. 04排查倾斜视角下的地形或天空显示问题

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/maplibre/maplibre-agent-skills --skill maplibre-terrain-rendering

安装后在 Claude Code 中输入/maplibre-terrain-rendering确认已加载。

详细介绍

MapLibre 地形渲染

raster-dem 源表示高程,而不是图片。有四种不同的方式可以绘制它,每种都有自己的图层类型或 API;这里大多数错误答案都是 MapLibre 从未支持过的 Mapbox GL JS 属性。

何时使用此技能

以下是你在了解原因之前可能观察到的症状:

  • 山体阴影对比过于强烈: 黑白分明的山脊、过曝的坡面、粉白的山谷——或者叠加多个山体阴影图层来柔化效果(用一个图层并设置 hillshade-method: "multidirectional")。
  • 动态高程着色: 地图需要在客户端按高度着色,且不使用预渲染瓦片(在 ["elevation"] 上使用 color-relief 图层,而不是在 raster 图层上使用 raster-color)。
  • 运行时等高线: 直接从 raster-dem 源生成等高线,无需预生成等高线瓦片集(使用 maplibre-contour,而不是手动编写 marching-squares 流程)。
  • 平坦的 3D 地形: 已启用 map.setTerrain(),但地形没有凸起(相机的 pitch: 0;提高 exaggeration 无法解决问题)。
  • 空白地平线: 倾斜相机后,地形上方显示空白的页面背景(没有根级别的 sky 对象或 map.setSky();MapLibre 没有 type: "sky" 图层)。
  • 属性静默失效: 山体阴影、天空或地形着色属性不起作用,也不报错(这是 MapLibre 从未支持过的 Mapbox GL JS 属性)。
  • 地形卡顿或掉帧: 启用地形后,平移或倾斜时画面卡顿(叠加的山体阴影绘制过程过多,或贴地 drape 图层过于密集)。

不属于此技能范围。 高程值错误、尖峰或颠倒,选择高程瓦片集、encoding,以及生成 DEM 瓦片——请参阅样式规范的 raster-dem 源页面, https://maplibre.org/maplibre-style-spec/sources/#raster-dem。关于山体阴影在样式其他图层中的位置,请参阅 maplibre-cartography。

你需要哪一种

目标绘制方式
在 2D 地图下方显示晕渲地形使用 hillshade 图层。无需 setTerrain——两者彼此独立
按高度着色(分层设色)使用 color-relief 图层(GL JS 5.6)
等高线,无需预生成瓦片集使用 maplibre-contour 库,为其提供 vector 源
倾斜的凸起表面,可在其上方飞行使用 map.setTerrain() 并设置相机倾角

这四种方式都读取同一个 raster-dem 源;一个源即可供它们共同使用。

山体阴影,以及无需叠加图层的强烈效果修正方法

每个 hillshade-* 属性都是 paint 属性。[1] 重要的默认值:hillshade-exaggeration 为 0.5,hillshade-illumination-direction 为 335,hillshade-illumination-anchor 为 viewport(光源固定在屏幕顶部,因此不会随地图方位旋转,除非你将其设为 map),hillshade-shadow-color 为 #000000,hillshade-highlight-color 为 #FFFFFF。

强烈的效果通常源于着色方法,而不是颜色。hillshade-method(GL JS 5.5) 支持 standard(默认值)、basic、combined、igor 和 multidirectional。[1] multidirectional 在一次绘制中从多个相互独立的方向照亮表面;igor 会尽量减小对其下方地图要素的影响。这两种方法都能通过单个图层柔化地形。

{
  "id": "hillshade",
  "type": "hillshade",
  "source": "terrain-dem",
  "paint": {
    "hillshade-method": "multidirectional",
    "hillshade-exaggeration": 0.4,
    "hillshade-illumination-anchor": "map",
    "hillshade-shadow-color": "rgba(30,40,80,0.45)",
    "hillshade-highlight-color": "rgba(255,240,200,0.4)"
  }
}

不要以不同的照明方向叠加多个 hillshade 图层。 在 5.5 之前,这是获得多方向着色的唯一方法;此后,它只是一个绘制属性,却要对同一 DEM 增加 N 次绘制过程。纯黑阴影和纯白高光是造成强烈效果的另一因素:为两者设置透明度,并在影像上使用暖色高光搭配冷色阴影。

Color-relief:按高度着色

color-relief(GL JS 5.6)会在客户端直接为 raster-dem 数据源着色;无需预渲染步骤,也不涉及 raster 图层。其绘制属性为 color-relief-color、color-relief-opacity(默认值为 1),以及从 GL JS 5.20 开始支持的 resampling。[1] 色带是一个针对 ["elevation"] 的 interpolate 表达式,该表达式返回高于 DEM 垂直基准面的米数,且仅在 color-relief-color 内有效。[2]

{
  "id": "hypsometric",
  "type": "color-relief",
  "source": "terrain-dem",
  "paint": {
    "color-relief-color": [
      "interpolate",
      ["linear"],
      ["elevation"],
      0,
      "#2c7bb6",
      500,
      "#abd9e9",
      1500,
      "#ffffbf",
      2500,
      "#fdae61",
      4000,
      "#ffffff"
    ],
    "color-relief-opacity": 0.8
  }
}

MapLibre 没有 raster-color、raster-value 或 raster-color-mix;这些属性属于另一种渲染器,会作为未知属性被忽略。指向 DEM 的 raster 图层显示的是打包后的 RGB 值,而不是色调。

实时生成等高线

maplibre-contour 会在 Web Worker 中根据相同的 DEM 瓦片生成矢量等高线瓦片,并通过已注册的协议提供服务——无需构建等高线瓦片集。[3]

import mlcontour from 'maplibre-contour';

const demSource = new mlcontour.DemSource({
  url: 'https://tiles.mapterhorn.com/{z}/{x}/{y}.webp',
  encoding: 'terrarium',
  maxzoom: 12,
  worker: true
});
demSource.setupMaplibre(maplibregl);

map.addSource('contours', {
  type: 'vector',
  tiles: [
    demSource.contourProtocolUrl({
      thresholds: { 11: [200, 1000], 12: [100, 500], 14: [50, 200] },
      elevationKey: 'ele',
      levelKey: 'level',
      contourLayer: 'contours'
    })
  ],
  maxzoom: 15
});

map.addLayer({
  id: 'contour-lines',
  type: 'line',
  source: 'contours',
  'source-layer': 'contours',
  paint: { 'line-color': 'rgba(0,0,0,0.4)', 'line-width': ['match', ['get', 'level'], 1, 1.2, 0.6] }
});

thresholds 将缩放级别映射到以米为单位的 [minor, major] 间隔;level 在主等高线上为 1,线宽和任何标注图层都以此为依据。[3] 这里的 encoding 必须与 DEM 完全一致,和样式数据源中的设置一样。

3D 地形、相机与天空

map.addSource('terrain-dem', { type: 'raster-dem', url: 'https://tiles.mapterhorn.com/tilejson.json' });
map.setTerrain({ source: 'terrain-dem', exaggeration: 1 });
map.setSky({
  'sky-color': '#199EF3',
  'sky-horizon-blend': 0.5,
  'horizon-color': '#ffffff',
  'horizon-fog-blend': 0.5,
  'fog-color': '#0000ff',
  'fog-ground-blend': 0.5
});
  • terrain 只接受 source 和 exaggeration(默认值为 1)。[4] 它是样式根级对象,可在样式中设置,也可通过 map.setTerrain() 设置;map.setTerrain(null) 会关闭地形。
  • 俯仰角决定地形是否可见。 当 pitch: 0 时,拉伸后的表面是从正上方看到的,因此看起来是平的。应先在地图上设置 pitch(或调用 map.easeTo({ pitch: 60 })),再判断地形是否损坏;相机倾斜后再提高 exaggeration,切勿用它来修复地图看起来是平的这一问题。
  • MapLibre 没有 sky 图层类型。 图层类型包括 fill、line、symbol、circle、heatmap、fill-extrusion、raster、hillshade、color-relief 和 background。[1] 天空是根级 sky 对象,也可通过 map.setSky() 设置:sky-color、horizon-color、fog-color、sky-horizon-blend、horizon-fog-blend、fog-ground-blend、atmosphere-blend。[5] sky-type、sky-atmosphere-sun 和 sky-atmosphere-sun-intensity 是 Mapbox GL JS 属性,在这里不起作用。fog-color 需要 3D 地形。[5]
  • 雾属于 sky 的一部分。 MapLibre GL JS 没有 setFog 方法,也没有根级 fog 对象;雾效由 sky 中的 fog-color、horizon-fog-blend 和 fog-ground-blend 实现。[5] [6]
  • 启用地形后,map.queryTerrainElevation(lngLat) 会返回某个位置下方的海拔。[6]

开销。 地形会解码 DEM 瓦片、构建网格,并重新绘制其上的每个图层,因此它是本页中开销最大的功能——在低端设备上,缩放级别和俯仰角较高时尤为明显。应尽量精简地形图层栈:共用一个 raster-dem 数据源、一两个高程图层,以及所需的叠加图层。

相关技能

参考资料

  1. 样式规范:图层 — hillshade 和 color-relief 绘制属性、默认值、hillshade-method 的取值以及完整的图层类型列表 — https://maplibre.org/maplibre-style-spec/layers/
  2. 样式规范:表达式 — ["elevation"],仅在 color-relief-color 中有效 — https://maplibre.org/maplibre-style-spec/expressions/
  3. maplibre-contour — DemSource、setupMaplibre、contourProtocolUrl — https://github.com/onthegomap/maplibre-contour
  4. 样式规范:地形 — https://maplibre.org/maplibre-style-spec/terrain/
  5. 样式规范:天空 — https://maplibre.org/maplibre-style-spec/sky/
  6. GL JS Map API — setTerrain、setSky、queryTerrainElevation — https://maplibre.org/maplibre-gl-js/docs/API/classes/Map/
  7. 示例 — 3D 地形、天空、雾效、地形、彩色地形图层、等高线、多方向山体阴影

此技能内容为快照。 如果主要来源与此内容相矛盾——包括上述参考资料、MapLibre 当前文档,或运行 MapLibre 时观察到的行为——请以主要来源为准。遵循该来源,然后报告此差异,并注明来源和你的 MapLibre 版本:修改你已安装的副本对其他人没有帮助,而且会在下次更新时被覆盖。

评论

支持 Markdown