12 KiB
Earth Real Terrain Plan
Goal
将 Earth 页当前的“程序噪声假地形”替换成基于真实 DEM 的可用地形层,使 地形 terrain 开关真正显示全球海拔起伏,而不是占位效果。
当前占位实现位于:
具体问题:
createTerrain()直接对球体顶点应用simplex noise- 没有真实海拔数据来源
- 没有分辨率分层
- 没有和当前相机/视角配套的性能控制
Constraints
本计划必须贴合当前 Earth 架构,而不是引入一套全新的地形引擎:
- 地球主体仍然是一个 Three.js sphere
- 海缆、登陆点、卫星、BGP 都已经建立在当前球体坐标系之上
- 不能为了地形把整页改成 Cesium/MapLibre Globe 之类的全栈替换
- 第一阶段优先做“真实可用”,不是一步到位做摄影测量级地形
Recommended Data Source
Primary recommendation
使用公开的 Terrarium 编码高程瓦片作为浏览器端高度来源,第一阶段优先接入:
- Mapzen/AWS
Terrariumelevation tiles
参考:Mapzen terrain tile format / Terrarium
原因:
- 已经是全球瓦片化高程
- 浏览器端按 tile 请求,最适合当前 Earth 这种在线 globe
- 编码简单稳定:
heightMeters = (R * 256 + G + B / 256) - 32768
- 不需要我们先离线拼整球 DEM
Data quality upgrade path
如果后面第一阶段效果确认可用,再逐步升级到底层源:
- Copernicus DEM GLO-30
参考:Copernicus DEM docs - 或用 Copernicus / SRTM / ASTER 等离线切成我们自己的 terrain tiles
这条升级路径适合第二阶段,不建议一开始就直接自建全球瓦片服务。
Why Not Replace the Engine
不建议为了地形直接切到 Cesium terrain / quantized mesh 引擎,原因:
- 现有 Earth 业务对象都依附当前球面坐标
- 切引擎会同时波及:
- 海缆绘制
- 卫星/轨迹
- BGP 标记
- HUD 与交互
- 这是“重做一页”,不是“给地形层接真实数据”
所以推荐路线是:
- 保持当前 sphere globe
- 为 sphere 增加真实高度位移层
Implementation Strategy
分三期推进。
Phase 1 — Global Heightmap Terrain Overlay
目标:
- 地形层切换后显示真实海拔起伏
- 全球范围可用
- 性能可控
做法:
- 新增 terrain 数据模块
建议文件:
frontend/public/earth/js/terrain.js
职责:
- 选择 DEM zoom level
- 请求 Terrarium tiles
- 解码 tile 高程
- 将高程重采样到当前地形球体网格
- 替换
createTerrain()
当前:
- 在 earth.js 中同步生成噪声地形
调整后:
createTerrain()只负责创建 terrain mesh 骨架- 真正的顶点位移由 terrain 模块异步注入
- 第一阶段采用“整球低分辨率位移”
不要一上来做动态 patch stitching。第一阶段更稳的办法是:
- 保留一张全球 terrain sphere
- 使用较低分辨率几何
- 例如
SphereGeometry(radius, 192, 192)或256/256
- 例如
- 运行时按一个固定地形 zoom(如
z=4或z=5)抓取覆盖全球的 Terrarium tiles - 将 tile 解码后重投影到经纬度采样网格
- 将每个球面顶点按真实高度抬升
这样第一阶段就能做到:
- 有真实地形
- 不需要复杂的局部 LOD
- 不会让现有球体对象体系爆炸
Phase 2 — View-Aware Refinement
目标:
- 正面可见区域更精细
- 背面与远处维持低成本
做法:
- 引入“基础全球地形 + 当前视角高分局部补丁”
- 正面区域额外抓更高 zoom 的高程 tile
- 只替换局部顶点位移或局部 overlay mesh
这一阶段适合在第一阶段稳定后做。
Phase 3 — Normals / Shading / Terrain UX
目标:
- 地形不仅有起伏,还更好看、更可读
包括:
- 根据高度生成更合理的 normals
- 调整 terrain material,使山脉/高原更易读
- 可选加入:
- hillshade
- contour lines
- snowline / bathymetry tint
Calibration Overlay Before More Terrain Tuning
在当前项目里,terrain 看起来“不像真地形”,不一定只是 DEM 或 exaggeration 不够,也可能是因为缺少稳定参照物。
没有清晰的海岸线、国界线和地表分层时,人眼很难判断:
- 山脉是不是在应该高的地方高
- terrain 是否真的贴在正确的大陆位置上
- 地球纹理、本初子午线、terrain 采样之间是否存在偏移
这里要明确区分两件事:
- 国界线不会修好错误的 terrain
- 但海岸线 / 国界线会让我们更容易判断 terrain 有没有贴准
所以在继续盲调 terrain 参数之前,建议先插入一个“校准参照层”阶段。
Recommended order for the calibration layer
- 海岸线
- 国界线
- 再继续调 terrain
原因:
- 海岸线比国界线更基础,也更接近真实地表边界
- 判断 terrain 是否贴准,最重要的是大陆边缘和山脉/海岸关系
- 国界线更多是政治边界,只能作为辅助参照
如果只加国界线,不加海岸线,效果仍然可能会怪,因为:
- 很多国界线本来就是人为直线
- 它们并不总是跟真实地形走
Suggested layer order during debugging
建议调试期临时把地球层次明确成:
- base earth texture
- coastline / borders overlay
- terrain relief
- cables / landing points / bgp / satellites
这样会比现在更容易判断:
- 山脉是否位于正确区域
- terrain 是否和地表对齐
- 国界/海岸是否漂移
Suggested data source for the calibration overlay
优先用 Natural Earth 的轻量全球矢量数据:
- 海岸线(coastline)
- Admin 0 国界线(country borders)
优点:
- 全球一致
- 轻量
- 很适合当前 Three.js globe 做 overlay
Recommended execution path
Phase A — Add reference overlays
先加两层可开关的参考线:
- 海岸线
- 国界线
这两层的目标不是最终美术表现,而是调试 / 校准。
Phase B — Recalibrate terrain against coastline
有了海岸线以后,再重新看 terrain:
- terrain 是否和大陆边缘错位
- 地球纹理、本初子午线、terrain 采样之间是否有固定偏移
Phase C — Decide whether to keep the current terrain path
这时再决定后面的路线:
- 如果发现真实高程整体是对的,只是缺少 shading / readability
继续保留当前 DEM + terrain overlay 路线 - 如果发现整球采样投影、本初子午线或 overlay 关系本身就很别扭
再考虑重做 terrain pipeline
Practical recommendation
当前阶段不建议“从头开始重做 terrain”。
更稳的策略是:
- 暂停继续盲调 terrain 参数
- 先补海岸线 / 国界线作为校准参照层
- 再基于参照层判断 terrain 是“参数没调好”,还是“整条实现路径有偏移”
Recommended Geometry Model
First usable model
保留一层独立 terrain sphere:
- base earth sphere:贴纹理、昼夜、海洋
- terrain sphere:略高于地球半径,真实高程位移
建议:
terrainBaseRadius = CONFIG.earthRadius + 0.2- 高度缩放使用真实米制换算,再乘一个可调 exaggeration
示例关系:
heightWorld = (elevationMeters / 6371000) * CONFIG.earthRadius * exaggeration
建议第一阶段 exaggeration = 1.3 ~ 1.8
因为完全真实比例在全球球体上会太平,看不出来。
Tile Decoding Plan
Terrarium decode
对于每个高程 tile 像素:
heightMeters = (R * 256 + G + B / 256) - 32768
Sampling path
对于 terrain mesh 上每个顶点:
- 将顶点方向转成经纬度
- 将经纬度映射到 Web Mercator tile 坐标
- 找到对应的 tile 和像素
- 解码高程
- 将顶点沿法线方向抬升
Needed helpers
建议新增:
latLonToTileXY(lat, lon, z)tilePixelFromLatLon(lat, lon, z, tileSize)decodeTerrariumHeight(r, g, b)
Caching Strategy
为了不让地形开关每次重开都重新抓全量 tile:
- terrain tile 按
z/x/y存到内存缓存 - terrain mesh 结果也缓存一份
- 当用户关闭/开启 terrain:
- 直接复用已有位移结果
建议:
Map<string, Float32Array | ImageBitmap>
Material Strategy
第一阶段不要复杂化。
建议 terrain material:
- 半透明低饱和地形色
- 比 base earth 稍亮或稍偏冷
- 保留当前 HUD 风格下的可读性
第一阶段不需要:
- 真实土地覆被纹理
- 独立卫星影像贴 terrain
因为那会和现有地球纹理、云层、昼夜 shader 打架。
Integration Points
Files to change
- earth.js
- 重写
createTerrain() - 删除 simplex noise 占位逻辑
- 重写
- main.js
- 初始化 terrain 数据加载
- 控制 terrain readiness / loading message
- controls.js
toggleTerrain逻辑保持,但应能区分:- mesh 已就绪
- 正在加载
- constants.js
- 新增
TERRAIN_CONFIG
- 新增
- 新文件:
frontend/public/earth/js/terrain.js
Suggested new config
建议新增:
export const TERRAIN_CONFIG = {
enabled: true,
tileSize: 256,
baseZoom: 4,
baseRadiusOffset: 0.2,
exaggeration: 1.5,
opacity: 0.55,
color: 0x6c876f,
maxConcurrentRequests: 8,
cacheEnabled: true,
};
Loading UX
地形第一次开启时,不能像现在一样瞬时切换。
建议:
- 如果地形数据尚未准备:
- 顶部状态条显示:
正在加载真实地形数据...
- 顶部状态条显示:
- 完成后:
真实地形已就绪
如果加载失败:
- 保留 base earth
- 显示轻量错误提示
- 不要让 terrain 开关卡死在“开”状态
Risks
1. Global tile count too high
即使 z=5 全球 tile 数也不少。
缓解:
- 第一阶段限定低 zoom
- 并发上限
- 缓存
2. Mesh resolution too low
如果球面分段太低,山脉会被抹平。
缓解:
- 第一阶段先选一个中等分辨率
- 用 exaggeration 保证可见性
3. Existing overlays may z-fight with terrain
海缆、登陆点、BGP、卫星相关对象都假设地球半径固定。
缓解:
- terrain sphere 单独作为 overlay
- overlay 保持略低或略高的固定 offset
- 必要时局部调整 landing point / cable altitude offset
4. Mercator sampling distortion near poles
Web Mercator 在高纬会有失真。
缓解:
- 第一阶段接受
- 后续若需要更严格极区质量,再上 geodetic reprojection pipeline
Acceptance Criteria
第一阶段完成后,应满足:
地形 terrain开关开启时,地表起伏明显不再是随机噪声- 喜马拉雅、安第斯、落基山、东非高原等全球大尺度地形可辨认
- 关闭/重新开启 terrain 不重复全量请求
- 不破坏:
- 海缆
- 卫星
- BGP
- 地球昼夜
- 天球层
Suggested Execution Order
- 引入
TERRAIN_CONFIG - 新建
terrain.js - 实现 Terrarium tile 请求与 decode
- 用低 zoom 全球 tile 构建真实 terrain sphere
- 接管
toggleTerrain() - 调整 terrain material 和高度 exaggeration
- 做缓存
- 再考虑第二阶段局部高分 refinement
Source References
- Mapzen Terrarium / AWS terrain tiles
Mapzen Terrain Tile Service - Terrarium tile experiments / format background
mapzen/terrarium - Copernicus DEM overview
Copernicus DEM docs
Recommendation Summary
如果现在就要开始做,我建议直接按这条路线开工:
- 第一阶段接入 Terrarium 全球高程 tile
- 替换掉当前 simplex 假地形
- 先做一层真实可见的全球 terrain overlay
- 等第一阶段稳定,再做视角高分 refinement
这是对当前项目风险最低、最贴合现有 Earth 架构的一条路。