返回知识库

GIS

影像图层

影像图层 封面
GISengine-webgpu影像图层OGC

前情回顾03 四叉树与 LOD 讲清了瓦片怎么调度(编号、四叉树、剔除、LOD)。本篇打开瓦片的内容黑盒——瓦片里装的是什么数据?不同地图服务的协议差在哪?多图层怎么在 GPU 上叠加?

直觉问题

打开任何一个 Web 地图应用,看到的”地图”往往不是一张图,而是好几层叠出来的:

  • 底层:卫星图(XYZ 协议,每张瓦片是预切片的 PNG)
  • 中层:道路和地名标注(WMS 协议,按需出图)
  • 顶层:自己画的矢量标记(WFS 或 MVT,客户端渲染)

这背后立刻冒出三个问题:

  1. OSM、天地图、Google、WMS 服务,URL 长得完全不一样——https://tile.openstreetmap.org/{z}/{x}/{y}.png vs https://server/wms?LAYERS=roads&BBOX=...,它们背后是什么不同的协议?为什么不能统一?
  2. 同一块地图区域,卫星图、道路、标注三层是怎么”叠”在一起的?是简单的 z-order 还是有什么数学混合?
  3. Mapbox/MapLibre 的”矢量瓦片”是什么?为什么和 OSM 的”栅格瓦片”不一样?

读完本篇,你能回答:“WMS 和 WMTS 差在哪?”、“栅格图层和矢量图层数据模型有何本质不同?”、“Multiply 混合模式与 Screen 混合模式公式差在哪?“

核心概念白话讲

用”网页图片”理解 XYZ 协议

XYZ 协议是最朴素的瓦片服务——每个瓦片就是一张 PNG/JPG/WebP 图片,URL 唯一决定是哪张:

https://tile.openstreetmap.org/10/842/388.png
                                 │  │   └─ y(行号)
                                 │  └───── x(列号)
                                 └──────── z(缩放级别)

打开浏览器直接访问这个 URL,你就拿到一张 256×256 的 PNG。整个 OSM 全球瓦片就是约 4192.7×10114^{19} \approx 2.7 \times 10^{11} 张这样的图片,预切片存在 CDN 上。客户端只要”知道 URL”就能拿。

用”打印报表”理解 WMS 协议

WMS(Web Map Service)反其道而行——它不预切片,每次请求都由服务器实时出图

https://server/wms?
  SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap
  &LAYERS=roads,rivers
  &BBOX=-74.05,40.70,-74.00,40.75
  &WIDTH=512&HEIGHT=512
  &FORMAT=image/png

服务器拿到这些参数(图层 + 地理范围 + 输出尺寸),渲染出一张 512×512 的 PNG 返回。同一个 BBOX 可以请求不同 LAYERS,灵活但慢——每次都要服务端渲染。

用”透明幻灯片”理解图层叠放

把多个图层想象成一叠透明幻灯片:

┌─────────────────────────┐
│  标注层(点/线/文字)     │ ← 最上层
├─────────────────────────┤
│  道路层(矢量线)         │
├─────────────────────────┤
│  行政边界(淡色面)       │
├─────────────────────────┤
│  卫星底图(不透明)       │ ← 最下层
└─────────────────────────┘

每层独立绘制,从下往上渲染。底层通常不透明(卫星图),上层通常带透明度(道路、标注)。

NOTE

关键认知:图层叠放不只是 z-order——还有**混合模式(blend mode)**决定像素如何合成。Normal 模式是 alpha 加权平均,Multiply/Screen/Overlay 等模式有完全不同的视觉效果。

用”调色板混合”理解多纹理混合

GPU 渲染瓦片时,每个瓦片可能有多个纹理(底图 + 道路 + 标注),需要在 fragment shader 里实时合成。这就是多纹理混合(multi-texture blending):

// GLSL 伪代码
vec4 base = texture2D(uBaseTex, vUV);        // 卫星底图
vec4 road = texture2D(uRoadTex, vUV);        // 道路
vec4 label = texture2D(uLabelTex, vUV);      // 标注

// 顺序混合
vec4 color = mix(base, road, road.a);        // Normal: alpha 加权
color = mix(color, label, label.a);
gl_FragColor = color;

mix(x, y, a) 是 GLSL 内置函数,等价于 x*(1-a) + y*a。多个图层就是嵌套 mix。

原理与数学/机制

1. 六大切片协议

Web GIS 的图层服务有 6 大主流协议,分两大类:

1.1 栅格协议(返回图片)

协议全称切片时机URL 形式标准来源
XYZSlippy Map预切片/{z}/{x}/{y}.pngOSM Wiki
TMSTile Map Service预切片/{z}/{x}/{y}.png(y 反向)OSGeo
WMSWeb Map Service动态出图?REQUEST=GetMap&BBOX=...OGC
WMTSWeb Map Tile Service预切片?REQUEST=GetTile 或 RESTOGC

1.2 矢量协议(返回几何)

协议全称数据形态切片时机标准来源
WFSWeb Feature ServiceGeoJSON / GML动态查询OGC
MVTMapbox Vector Tiles二进制 PBF预切片Mapbox Spec

1.3 协议详解

XYZ vs TMS:见 Phase 3,y 轴方向相反。

WMS(动态出图)

  • 服务器每次请求都实时渲染,性能远不如预切片
  • 优势:灵活——同一 BBOX 可以请求不同图层、不同样式、不同 CRS
  • 适用:低频访问、样式经常变化的服务(如某政府专题图)

WMTS(WMS 的预切片版)

  • 把 WMS 的”动态出图”换成”预切片 + 缓存”
  • 接口形式:REST 风格 /{Layer}/{TileMatrixSet}/{TileMatrix}/{TileRow}/{TileCol}.png 或 KVP(键值对 URL)
  • OGC 标准下 WMTS 默认用 EPSG:4326(geodetic)瓦片方案,但也可配置 EPSG:3857
  • 适用:大规模、高并发地图服务(政府门户、企业底图)

WFS(矢量数据查询)

  • 返回的不是图片,是 GeoJSON / GML 格式的矢量数据
  • 客户端拿到几何后自己渲染(点画成什么颜色、线画多粗都客户端决定)
  • 支持空间过滤(BBOX)和属性过滤(CQL_FILTER
  • 适用:矢量对象交互(点击高亮、属性查询、客户端样式)

MVT(Mapbox Vector Tiles)

  • 矢量数据按 z/x/y 预切片成二进制 PBF 文件
  • 介于 XYZ(栅格预切片)和 WFS(矢量动态)之间——既保留矢量的”客户端渲染”灵活性,又有预切片的”高并发”性能
  • Mapbox / MapLibre / deck.gl 主战场
  • 适用:现代 Web 地图(Mapbox Studio 自定义样式、海量数据流畅缩放)

IMPORTANT

协议选型决策树

  • 数据不变 → 栅格预切片(XYZ / TMS / WMTS)
  • 灵活低频访问 → WMS 动态出图
  • 矢量交互(点击、样式)→ MVT 预切片矢量(现代)或 WFS 动态矢量(传统)

2. OGC 标准体系

**OGC(Open Geospatial Consortium)**是国际地理信息标准组织,制定了一族 Web 服务标准:

              OGC 标准

        ┌───────┼────────┐
       服务     数据       编码
        │       │         │
   ┌────┼───┐  ├─GML    ├─WKT
  WMS  WMTS WFS ├─GeoJSON └─WKB

               CityGML
               3D Tiles(Phase 9)
  • 服务标准:WMS / WMTS / WFS / WCS(栅格数据)/ WPS(处理服务)
  • 编码标准:GML(XML 矢量)/ GeoJSON / CityGML(三维城市)/ 3D Tiles(三维瓦片)
  • 角色:OGC 标准让不同厂商的 GIS 软件(ESRI / QGIS / 开源引擎)能互操作——同一份 WMS 服务可以被 QGIS、ArcGIS、OpenLayers 同时消费

3. 栅格图层 vs 矢量图层

两种图层数据模型本质不同:

维度栅格图层矢量图层
数据本质像素矩阵(每个像素有 RGB 值)几何对象(点 / 线 / 面 + 属性)
缩放表现放大后模糊(像素被拉伸)无限放大保持锐利
文件大小大(每瓦片 256×256×3 = 192 KB)小(PBF 编码紧凑)
渲染成本低(GPU 直接纹理贴图)高(客户端绘制几何)
样式灵活性低(样式在服务端固化)高(客户端自由定义)
交互能力弱(只能识别瓦片级别)强(每个要素可独立交互)
典型协议XYZ / TMS / WMS / WMTSWFS / MVT
典型场景卫星图、地形渲染图道路、行政边界、自定义标记

4. 纹理混合数学

4.1 Normal + alpha blending(最常用)

两个图层叠加,Normal 模式 + alpha 通道:

Cout=Cbase(1αoverlay)+CoverlayαoverlayC_{\text{out}} = C_{\text{base}} \cdot (1 - \alpha_{\text{overlay}}) + C_{\text{overlay}} \cdot \alpha_{\text{overlay}}

其中 CC 是 RGB 颜色向量,α\alpha 是 overlay 图层的不透明度(0-1)。

GLSLmix(base, overlay, overlay.a)

4.2 Multiply(正片叠底)

每个通道相乘(颜色归一化到 [0,1][0, 1]):

Cout=CbaseCoverlayC_{\text{out}} = C_{\text{base}} \cdot C_{\text{overlay}}

效果:颜色变暗——白色(1.0)保持底色不变,黑色(0.0)变全黑。常用于阴影叠加纸质效果

4.3 Screen(滤色)

Multiply 的反向操作:

Cout=1(1Cbase)(1Coverlay)C_{\text{out}} = 1 - (1 - C_{\text{base}})(1 - C_{\text{overlay}})

效果:颜色变亮——黑色保持底色不变,白色变全白。常用于光晕、发光效果夜间地图

4.4 Overlay(叠加)

Multiply 和 Screen 的混合——根据底色亮度分支:

Cout={2CbaseCoverlayif Cbase<0.512(1Cbase)(1Coverlay)if Cbase0.5C_{\text{out}} = \begin{cases} 2 C_{\text{base}} C_{\text{overlay}} & \text{if } C_{\text{base}} < 0.5 \\ 1 - 2(1 - C_{\text{base}})(1 - C_{\text{overlay}}) & \text{if } C_{\text{base}} \geq 0.5 \end{cases}

效果:暗处更暗、亮处更亮(增加对比度),中间灰保持。常用于地形阴影增强对比度提升

4.5 4 种混合模式对比

模式公式效果Web GIS 典型用途
Normalα\alpha 加权平均标准透明叠加95% 场景(道路叠加在卫星图上)
MultiplyCbCoC_b \cdot C_o变暗阴影、纸质效果
Screen1(1Cb)(1Co)1 - (1-C_b)(1-C_o)变亮光晕、夜间地图
Overlay暗处 Multiply,亮处 Screen增加对比度地形阴影增强

TIP

生产建议:默认用 Normal + alpha 即可。Multiply / Screen / Overlay 是高级用法,主要用于艺术化地图样式(如夜间模式、复古地图)或地形渲染增强

4.6 多层嵌套混合

3 个图层(base + layer1 + layer2)按 Normal 模式顺序混合:

Cfinal=mix(mix(Cbase,C1,α1),C2,α2)C_{\text{final}} = \text{mix}\bigl(\text{mix}(C_{\text{base}}, C_1, \alpha_1), C_2, \alpha_2\bigr)

GLSL 写法:

vec4 color = mix(base, layer1, layer1.a);
color = mix(color, layer2, layer2.a);

每多一层就多嵌套一次 mix。Web GIS 引擎通常限制图层数量(如最多 8 层),避免 shader 嵌套过深影响性能。

5. HTTP 并发优化

瓦片加载是高并发场景——单次缩放可能触发 50-200 个瓦片请求。HTTP 协议版本对并发性能影响巨大:

协议单连接并发数典型场景瓦片加载性能
HTTP/1.16(浏览器限制)老旧服务器、自托管慢,需 域名分片(domain sharding)
HTTP/2数百(多路复用)主流 CDN(Cloudflare / CloudFront)快,单连接多请求
HTTP/3数百(QUIC)Google / Cloudflare 边缘更快(无队头阻塞)

域名分片(HTTP/1.1 时代)

HTTP/1.1 单域名只能并发 6 个请求。瓦片服务通常用多个子域名扩展并发:

https://a.tile.openstreetmap.org/{z}/{x}/{y}.png
https://b.tile.openstreetmap.org/{z}/{x}/{y}.png
https://c.tile.openstreetmap.org/{z}/{x}/{y}.png

3 个子域名 × 6 连接 = 18 个并发。OSM / Google Maps 早期都用这种 trick。

WARNING

HTTP/2 时代不要再域名分片——多路复用让单域名可并发数百请求,反而多域名增加 DNS / TLS 握手开销。OSM 在 HTTP/2 CDN 上已不推荐 a/b/c 子域名。

6. 图层管线流程

图 1:从图层声明到屏幕像素的完整管线(每个图层独立走 A→E,F 是所有图层在 shader 内合成)

关键节点

  • A:用户声明图层(如 addLayer(type='xyz', url='...', opacity=0.8)
  • B:根据相机位置算出本帧需要的瓦片 z/x/y,拼接 URL
  • C:HTTP/2 单连接并发请求多个瓦片
  • D:PNG → ImageBitmap,PBF → 几何数据
  • E:把 ImageBitmap 上传到 GPU 作为纹理
  • F:fragment shader 内对多个纹理做 mix 混合
  • G:最终颜色写到 Framebuffer(参考 Phase 1 渲染循环 的步骤四/五/六)

可视化对比与动手实验

对比表一:6 种切片协议全景

协议数据形态切片时机URL 形式缓存策略典型使用者
XYZ栅格 PNG预切片/{z}/{x}/{y}.pngCDNOSM / Google Maps / 百度
TMS栅格 PNG预切片/{z}/{x}/{y}.png(y 反向)CDNNASA GIBS / 老 OGC
WMS栅格 PNG动态?REQUEST=GetMap&BBOX=...无(每次实时)政府专题图
WMTS栅格 PNG预切片REST 或 KVPCDN政府门户、企业底图
WFS矢量 GeoJSON/GML动态查询?REQUEST=GetFeature&BBOX=...传统 GIS 互操作
MVT矢量 PBF预切片/{z}/{x}/{y}.pbfCDNMapbox / MapLibre / deck.gl

对比表二:栅格 vs 矢量图层数据模型

维度栅格图层矢量图层
数据本质像素矩阵几何对象 + 属性
缩放表现放大模糊无限锐利
文件大小192 KB/瓦片5-50 KB/瓦片(PBF)
渲染成本低(GPU 贴图)高(客户端绘制)
样式灵活性低(服务端固化)高(客户端定义)
交互能力弱(瓦片级)强(要素级)
典型协议XYZ / WMS / WMTSWFS / MVT

对比表三:4 种图层混合模式

模式数学公式视觉效果典型用途
NormalCb(1α)+CoαC_b(1-\alpha) + C_o\alpha标准透明叠加95% 场景
MultiplyCbCoC_b \cdot C_o变暗阴影、纸质感
Screen1(1Cb)(1Co)1-(1-C_b)(1-C_o)变亮光晕、夜间地图
Overlay暗处 Multiply,亮处 Screen增加对比度地形阴影增强

动手实验一:观察 OSM Tile URL

打开 OpenStreetMap,缩放到某城市,右键任意瓦片 → 复制图片地址

  • URL 形如 https://tile.openstreetmap.org/15/27176/12421.png
  • 注意 15 是 z(缩放级别),27176 是 x,12421 是 y
  • 改 URL 最后一个数字看相邻瓦片

动手实验二:用 QGIS 添加 WMS 服务

如果你装了 QGIS,添加一个公共 WMS:

  1. Layer → Add Layer → Add WMS Layer
  2. 添加服务 URL(如 NOAA WMS
  3. 选择 Layer,点击 Add
  4. 在 Network 面板观察请求 URL(注意 BBOXWIDTHHEIGHTFORMAT 等参数)
  5. 缩放时观察 WMS 每次都重新请求(动态出图,与 XYZ 的预切片对比明显)

动手实验三:用浏览器 DevTools 观察瓦片并发

打开任意 Web 地图,按 F12 → Network → 过滤 png

  • HTTP/1.1 站点:同时最多 6 个请求,其余排队
  • HTTP/2 站点(OSM 现在是 HTTP/2):单连接同时跑 50+ 请求
  • 注意 Protocol 列(h2 = HTTP/2,http/1.1 = HTTP/1.1)

常见误区

WARNING

误区 1:以为 WMS 也有瓦片缓存。 ✅ 正确:WMS 是动态出图——每次请求都实时渲染。要缓存就用 WMTS(同 OGC 标准的预切片版本)。

WARNING

误区 2:以为 WFS 返回图片。 ✅ 正确:WFS 返回矢量数据(GeoJSON / GML),客户端拿到几何后自己渲染。返回图片的是 WMS / WMTS。

WARNING

误区 3:以为图层叠放就是按 z-order。 ✅ 正确:z-order 决定绘制顺序,blend mode 决定像素如何合成。Normal 是 alpha 加权平均,Multiply / Screen / Overlay 是不同的数学公式。

WARNING

误区 4:以为 HTTP/2 对瓦片加载影响不大。 ✅ 正确:HTTP/1.1 单域名只能并发 6 个请求;HTTP/2 多路复用让单连接并发数百个。瓦片是高并发场景(单次缩放 50-200 个请求),HTTP/2 让加载时间缩短 3-5 倍。

WARNING

误区 5:以为矢量图层也走栅格瓦片协议。 ✅ 正确:矢量图层有专属协议——传统用 WFS(动态查询 GeoJSON),现代用 MVT(预切片 PBF)。两者都返回几何数据,客户端 GPU 绘制。

WARNING

误区 6:以为 MVT 和 WFS 是同一回事。 ✅ 正确:MVT 是预切片的矢量瓦片(按 z/x/y 切,PBF 二进制编码),高并发场景用;WFS 是动态查询(按 BBOX + CQL_FILTER 实时返回),适合低频但灵活的矢量交互。

WARNING

误区 7:以为图层数量没有上限。 ✅ 正确:每多一层 fragment shader 多嵌套一次 mix(),性能线性下降。Web GIS 引擎通常限制最多 8 层活动图层。

延伸阅读与自测

权威参考

自测题

  1. 协议选型:要做一个”实时空气质量地图”,数据每 5 分钟更新一次,全国范围。会选 XYZ / WMS / WMTS / WFS / MVT 哪个?为什么?
  2. 混合模式选择:要把”地形阴影”层叠加到”卫星图”层上,让山的立体感更强。选 Normal / Multiply / Screen / Overlay 哪个?为什么?
  3. WMS vs WMTS:同一个 OGC 服务的 WMS 和 WMTS 接口,请求 1000 次同一个区域,哪个更快?为什么?WMTS 的”快”付出了什么代价?
  4. MVT vs WFS:为什么 Mapbox 选 MVT 而不是 WFS?两者都是矢量协议,根本差异是什么?
  5. HTTP/2 与域名分片:你接手了一个老瓦片服务(用 a/b/c.tile.example.com 子域名分片)。现在 CDN 升级到 HTTP/2,要不要保留域名分片?为什么?

下一篇导引05 地形与 Worker 将打开瓦片的第三个维度——高程。DEM 数据怎么编码(RGB / BIL)?大地水准面与椭球面差 ±100 m 怎么修正?Web Worker 如何让地形解码不阻塞渲染?