05-research-overlay-rectangle-pop-mechanisms.md 3.8 KB

# 调研 —— 精细矩形跳变的成因与可用手段

Type: research Status: resolved Labels: wayfinder:research Blocked by: None

进度:100%

已关闭。产物:research/overlay-rectangle-pop-mechanisms.md。只做只读调研;未改任何文件、未跑 build/dev。

Question

从全球飞到县城视角的途中,「全球粗底图 → 本地精细影像矩形」为什么会突兀地跳出一块颜色明显不同的方形区域?引擎里已有哪些可用来消除或掩盖它的手段,各自的边界是什么?

Answer

结论:矩形边缘是 GLSL 硬切、引擎零羽化零交叉淡入、且精细层并非"近了才加载";跳变有两类,一类是矩形整体出现,一类是矩形内部逐级换挡。

  1. 图层构成:全局底图=Cesium 自带离线 Natural Earth II(TMS),且只有 0–2 级(tilemapresource.xml 的 TileSet order 0/1/2)→ 最高约 19.5 km/像素,整个沅陵在底图上只有约 6×6 个像素。精细层=/gis/pic3 的 TMS,挂在 provider 的 rectangle 内,画在底图之上,层序 [NaturalEarthII, 精细层],初始色 #04121f。

  2. 精细层是全不透明的,且 minimumLevel: 0 是空操作。ImageryLayer.alpha 默认 1.0;UrlTemplateImageryProvider 的 _minimumLevel 默认就是 0,所以配置里那句 "minimumLevel": 0 等于没写 —— 精细层从自身金字塔最粗级别起就有资格被请求,不存在"靠近了才开始加载"。

  3. 边缘是硬切,没有羽化。GlobeFS.glsl 用 step() 生成 0/1 遮罩(textureAlpha *= alphaMultiplier.x * alphaMultiplier.y),无羽化宽度、无混合距离、无抖动。矩形外由底图层兜着(isBaseLayer() 的 texel 拉伸),两层之间没有任何内置交叉淡入 —— 整个引擎里没有 imagery fade 逻辑可复用,任何渐显都得手写。

  4. 跳变有两类,不要只处理一类:

    • (a) 矩形首批瓦片到位时整体出现:GlobeSurfaceTileProvider 对未就绪或无影像的层直接 continue,所以该层是"一帧内从无到全不透明"。
    • (b) 矩形内部持续逐级换挡:影像级别被地形级别牵着走(ImageryLayer 用 terrainProvider.getLevelMaximumGeometricError(tile.level) 推 imageryLevel),每次地形 LOD 细化都连带提升影像级别、无过渡替换。
  5. 可用手段与其边界:

    • ImageryLayer.alpha —— 可写,但只是整层一个 uniform(能整体淡入淡出,不能羽化边缘);且越过 0.0 会翻转 shader 变体(有重编译/切换成本)。JSDoc 里那个按瓦片的函数形式在随包引擎里没有实现。
    • ImageryLayer.show —— 二元开关;隐藏底图会把精细层提升为 base layer(于是它的 texel 被拉伸到全球),是个陷阱。
    • ImageryLayer.rectangle —— 只读,不能动画。
    • minimumTerrainLevel / maximumTerrainLevel —— 可按地形级别做硬门("太远就不显示"最省事的近似闸门),但是硬开关、不是渐变。
    • brightness/contrast/gamma/saturation/hue —— 只能对齐颜色,抹不掉分辨率台阶。
    • 逐帧驱动点:Scene.preRender / postRender;Camera.changed(默认 percentageChanged = 0.5,偏粗,需调小);globe.tileLoadProgressEvent(唯一的加载进度信号)。
    • 注意:仓库用 new ImageryLayer(provider) 建精细层,而 ImageryLayer.readyEvent 只在 fromProviderAsync 工厂里触发 —— 所以精细层没有现成的"就绪"信号。
  6. 历史:票 21 与票 30 都没有尝试或推迟过颜色对齐、边缘羽化、交叉淡入或 LOD 过渡 —— 这是全新工作面。