矢量数据与折线(Vector Data and Polylines)
虚拟地球同时使用两类核心数据:
- 栅格数据(raster):地形、影像,负责“颜值”。
- 矢量数据(vector):点、线、面,负责“干活”——从城市规划到作战指挥。
图 7.1(b) 展示了三种基本矢量形态:河流是折线(polyline),国家是多边形(polygon),城市是点(point)。
接下来三章节将逐一介绍现代虚拟地球中 折线、多边形、点 的渲染与预处理技术(三角化、纹理打包等)。
10.1 矢量数据来源
| 格式 | 特点 |
|---|---|
| Shapefile (Esri) | .shp 存几何,.shx 索引,.dbf 存属性;所有要素类型一致。 |
| KML (OGC) | XML 结构,可携带样式、导航、外链;libkml 支持 C++/Java/Python。 |
10.2 解决 z-fighting
矢量数据与椭球面之间会出现两种深度冲突:
- 共面冲突:线段与三角片面共面 → z-fighting。
- 切穿冲突:线段略低于椭球面 → 被深度测试剔除。
解决方案:写入“中值深度”
- 在片元着色器(或光线投射)中,计算射线与椭球的 前后两个交点,取时间中值:
vec3 avgPos = eye + mix(i.nearTime, i.farTime, 0.5) * rayDir; gl_FragDepth = computeDepth(avgPos); - 照明仍使用实际交点坐标。
- 扩展:可为不同对象准备两套深度缓冲(正常 vs 中值)。
10.3 折线渲染
9.3.1 批处理(Batching)
目标:把大量小折线塞进一次 Draw Call,减少 CPU/GPU 往返。
| 方法 | 顶点数 | 索引数 | 说明 |
|---|---|---|---|
| Lines(逐线段) | 2n-2 | 0 | 简单,但双倍顶点。 |
| Indexed Lines | n | 2n-2 | 省显存,GPU 顶点缓存友好。 |
| Indexed Line Strips + Primitive Restart | n | n+1 | 单 Draw Call 渲染多条折线,最省。 |
示例:1000 点折线
- Line Strip:32 000 B
- Indexed Lines:39 996 B
- Indexed Line Strips:34 002 B
10.3.2 静态缓冲
- 边界、道路等极少变更 → 一次上传 GPU,使用
BufferHint.StaticDraw。 - 动态轨迹可配合静态索引 + 动态顶点(仅追加顶点,索引不变)。
10.3.3 宽线(Wide Lines)
- 旧 API:
glLineWidth已被弃用。 - 现代做法:几何着色器把线段扩展为 像素宽度的四边形(图 7.8)。
- 将端点投影到窗口坐标。
- 计算法线,沿法线挤出 ±width/2。
- 输出三角形带。
- 锐角缝隙:在端点附加一个圆点即可掩盖(图 7.10)。
10.3.4 描边线(Outlined Lines)
需求:内色 + 边框,使折线更醒目(图 7.11)。
| 方案 | 实现要点 |
|---|---|
| 两遍渲染 | 先外框(大宽度),再内芯;需模板缓冲防 z-fighting。 |
| 几何着色器一次生成 | 6 个三角形(内 2 + 外 4),边缘锯齿需 MSAA。 |
| 纹理法(推荐) | 1D 纹理横跨线宽:R 通道控制内/外颜色插值,G 通道控制透明度衰减 → 无内锯齿,外边界自动抗锯齿(图 7.13)。 |
| 纹理宽度 = interior + outline×2 + 2(边缘透明像素)。 |
纹理只存 0/1,不存颜色,因此可复用于不同颜色组合。
10.3.5 采样与 LOD
- 直线段过椭球:洛杉矶—纽约直线会切穿地球。
→ 使用 2.4 节算法在椭球面上 等角重采样。 - 海量点折线:
- 先用 Douglas-Peucker 离线生成多级离散 LOD。
- 按图层可见高度切换,而非逐折线 LOD(图层先关,LOD 后省)。
动手实践
运行 Chapter07VectorData 即可加载 shapefile,实时观察折线、多边形、布告板渲染效果。
1508

被折叠的 条评论
为什么被折叠?



