geopro/.superpowers/sdd/task-12d-report.md

9.6 KiB
Raw Permalink Blame History

Task 12d 收尾探针报告 —— 视觉调优 + fps 预算 + 可交互开窗

实测环境: 本机 RTX 3060 / VTK 9.6 / MSVC+Ninja。store: tmp/store_lod_001 (level0 = 44476×29×162, 4 层金字塔, brick=64, 2.09 亿体素)。

所有数字为真实离屏实测, 双闸(纹理错捕获 + 回读非空像素)防假帧率。


状态

完成。三件事全部落地、编译通过、离屏实测出数:

  • tune 视觉调优: 出 lod-tuned-local.png / lod-tuned-overview.png, 打印调优前后 fps 对照。
  • fps-budget: 递增全分辨率窗口 fps 表 + 每帧体素预算结论。
  • view: 真窗口 + interactor + 缩放切 LOD + 屏幕 fps 文本; 离屏 --smoke 通过不崩。

改动文件: tools/gpr_poc/main.cpp (新增 3 个子命令 + 视觉调优共享构件), 新增两张调优截图, 追加写 docs/superpowers/plans/poc-results-C.md


① 视觉调优: 调优前后 fps 对照(证实视觉调优 fps 近乎中性)

gpr_poc tune <store> --opacity 0.7 --exagg 8 --localBricks 4 (level0 256×29×162 局部段):

配置 色阶 不透明度 垂向夸张 局部 fps
调优前(基线) 蓝-白-红线性单斜坡 0.15 1× 323.3
调优后 结构色阶(深蓝→青→白→黄→红) + 双端斜坡 0.7 8× 349.2

fps 变化 = 8.0%(即调优后反而更快)。完全证实探针认知:

  • 隔离实验(--exagg 1): 不透明度 0.15→0.5/0.6、换结构色阶, fps 5.5%(更快)。 → 配色/不透明度对 fps 近乎中性, 调高不透明度甚至更快(光线提前终止)。
  • 隔离实验(--opacity 0.9 --exagg 10): fps 反而 +49%(更快)。 双端斜坡把占多数的近零背景设透明, 不透明片段少 + 提前终止, 抵消了夸张放大的屏占。
  • 早先一版"线性单斜坡 + exagg 8"曾掉 34%, 经排查 掉帧全部来自垂向夸张(8× 放大薄轴 → 屏占变大 → ray-cast 片段变多), 与不透明度/配色无关。改用双端斜坡(背景透明)后 即转为净加速。

关键视觉修复: GPR/地震体值集中在零附近(背景), 强反射在正负两端。原线性单斜坡让 近零背景填满体、遮住结构(实测渲出一块均匀蓝板, 无结构)。改为双端斜坡(中段透明 + 正负两端不透明) 后, 截面的层状反射(地层条带)清晰可辨。

调优截图:

  • docs/superpowers/plans/poc-lod-shots/lod-tuned-local.png —— 全分辨率局部段, 可见多条水平层状反射条带(地层结构)+ 一处相干蓝色异常体。
  • docs/superpowers/plans/poc-lod-shots/lod-tuned-overview.png —— 粗层(level2)概览。物理真实: 整线 2.2km×1.5m×8m 极扁, 概览就是一条细带(可接受)。

诚实说明: 体物理纵横比极端(X≈2.2km vs Y≈1.5m / Z≈8m), 即便取局部段 + 8× 夸张, 单帧里结构仍偏小、偏一隅, 背景大片黑。结构确实可辨(层状条带 + 异常体), 但"一眼炸裂" 受物理形态限制——这正是 brief 预期的"细带本质"。production 可配可调色阶/取景控件让 用户交互找最佳视角(即 ③ view)。


② fps 预算: 递增全分辨率(level0)窗口 → 每帧体素预算

gpr_poc fps-budget <store> --bricks 4,16,64,128,256,512,695 --frames 90 (沿线中段递增 brick 列, 单 image 整段体绘制, 双闸):

brick 段 维度 体素数 体绘制 fps ≥30 备注
4 256×29×162 1,202,688 218.3
16 1024×29×162 4,810,752 155.7
64 4096×29×162 19,243,008 240.9
128 8192×29×162 38,486,016 305.8
256 16384×29×162 76,972,032 329.7 触达 GL_MAX_3D_TEXTURE_SIZE=16384
512 32768×29×162 153,944,064 INVALID X=32768>16384, 纹理墙, 双闸标 INVALID
695 44476×29×162 208,948,248 INVALID 同上

每帧体素预算结论(重要, 与 brief 框架略有出入但更真实)

  • fps 在所有可上传测点(≤16384 单轴)始终 ≫ 30(218~330fps), 全程没跌破 30。 fps 不随 体素数单调下降(甚至上升), 因 ray-cast 成本主要由屏占 × 采样步长决定, 而薄维度(Y29/Z162) 使光线路径短, 单 3D 纹理上传成功后体素总数不是瓶颈。
  • 真正的硬墙是 GL_MAX_3D_TEXTURE_SIZE = 16384: 单轴超 16384 → 整段无法成单张 3D 纹理 (512/695 行双闸正确判 INVALID, 绝不当真上报)。
  • 因此本数据集上, "单张 3D 纹理的每帧体素预算" = 单轴 ≤16384 → ≈ 7700 万体素(256 brick 列) 跑 ~330fps 仍极宽裕; 限制 production LOD 每帧块数的不是 30fps 阈值, 而是 16384 纹理墙—— 超墙必须切块(MultiBlock / SetPartitions / 本机核外 OutOfCoreSource)。
  • fps 驱动的体素预算(跌破 30)只会在远更大/更稠密体或多块叠加渲染时出现; 本数据集薄维度下 GPU 余量充足, 未触达。

这与 brief"找 fps<30 阈值"的设想不同, 但是实测真相: 本数据集的命门是纹理尺寸墙, 不是帧率墙。如实记录。


gpr_poc view <store> —— 真窗口可交互(给用户肉眼测 + 最低配机跑)

实现要点:

  • vtkRenderWindow + vtkRenderWindowInteractor(vtkInteractorStyleTrackballCamera), 挂 OutOfCoreSource(核外 LOD + 视野选块, budget 限驻留, 内存恒定)。
  • 相机变化(EndInteractionEvent)→ source.update(camera) 重选 LOD/视野块 → 重建 MultiBlock → 重渲。缩放跨越距离/对角线档位时 LOD 真切换(离屏 smoke 实测 level 1↔0 切换)。
  • 屏幕左上角 vtkTextActor 实时显示 fps | LOD level | blocks | exagg, 每帧更新。
  • 默认结构色阶 + 双端斜坡不透明度 + 垂向夸张(同 ①)。
  • 参数: --exagg N --opacity F --budget K(K=每帧最大全分辨率块数, 接 ② 预算)。

离屏 smoke(view --smoke)实测:

预热: level=1 视野块=696/696 驻留=64 渲染块=64
近观 level=1 → 拉远 level=1 → 再拉近 level=0
LOD 随缩放切换  : 是 ✔
纹理维度错误    : 否
渲出非空像素    : 是 (近=1024000 远拉近=1024000)
smoke 结果      : OK ✔ 不崩

view 命令用法

gpr_poc view <storeDir> [--exagg 8] [--opacity 0.6] [--budget 64] [--smoke]
  • 不带 --smoke = 开真窗口可交互(留给用户跑)。
  • --smoke = 离屏建管线 + 模拟缩放验 LOD 切换 + 验不崩(CI/无显示环境用)。

给用户的肉眼测试说明(请转达用户)

启动命令(在已构建的仓库根目录):

build\release\tools\gpr_poc\gpr_poc.exe view tmp\store_lod_001 --exagg 8 --opacity 0.6 --budget 64
  • DLL/PATH: 无需手设。CMake 已把 VTK/Qt 等运行时 DLL 拷到 exe 旁(gpr_poc.exe 同目录), 直接双击/命令行运行即可。
  • 若换其它 store, 把 tmp\store_lod_001 换成你的金字塔 store 目录(需先 gpr_poc build ... --levels 3)。

操作:

  • 滚轮: 向前滚拉近 → 应看到全分辨率结构(屏幕 LOD level 数字变小, 0=最细); 向后滚拉远 → 变粗层概览(level 数字变大, 体变糊)。
  • 左键拖动: 旋转视角(TrackballCamera)。
  • q 键 / 关窗: 退出。

判断点(可接受标准):

  1. 拉近后能否看清地质结构: 局部段应呈现水平层状反射条带(地层)+ 可辨的相干异常体。 能看出层次即可接受(受物理细带形态限制, 不会像规则立方体那样饱满)。
  2. 概览(细带)可不可接受: 拉远后是一条细长带(整线 2.2km×1.5m×8m 物理真实), 接受它是细带。
  3. 拉近/拉远切 LOD 时卡不卡、糊→清过渡能不能接受: 切换应顺滑, 无明显卡死/长 stall (本机切换 ~5-9ms, 远小于 1 个 60Hz 帧 16.7ms, 不可感)。
  4. 屏幕 fps 是否 ≥30: 屏幕左上角实时 fps。本机(RTX 3060)远超 30(数百 fps); 最低配机重点看这条——拉到最细 LOD、最大夸张时 fps 是否仍 ≥30。

最低配怎么跑:

  • 把整个 build\release\tools\gpr_poc\ 目录(含所有 DLL)+ 一个 store 目录拷到目标机, 跑上面的 view 命令, 肉眼看屏幕 fps 与交互流畅度。
  • 或无显示/批处理场景跑 gpr_poc fps-budget tmp\store_lod_001 出该机的体素-fps 表对照。

最低配未验声明

本探针仅在本机 RTX 3060 跑出上限数字(数百 fps, 余量充足)。最低配机器未验证, 需用户拿目标机跑 gpr_poc view <store>(肉眼判 fps≥30 + 交互流畅)或 gpr_poc fps-budget <store> (出该机体素-fps 表)。production 是否对最低配可用, 以目标机实测为准。


Concerns

  1. 视觉天花板受物理形态限制: 体极扁(2.2km×1.5m×8m), 单帧结构偏小偏一隅。这是数据物理 真实, 非 bug; production 应给用户交互色阶/取景/裁剪控件(view 已具备旋转缩放, 色阶可参数化)。
  2. fps 不是本数据集的瓶颈, 纹理尺寸墙(16384)才是: 与 brief"找 fps<30 阈值"设想不同。 每帧体素预算结论是"单轴 ≤16384 即可单纹理上传, fps 仍 ≫30", 超墙必须切块。如实记录。
  3. view 的 LOD 阈值按未夸张几何标定: pickLevel 用 level0 原始对角线算距离比, 而 actor 已 SetScale(1,exagg,exagg)。夸张会轻微平移"缩放-LOD 映射"档位, 但切换仍正常触发 (smoke 实测 level 1↔0)。若用户觉得切档时机别扭, 后续可让 pickLevel 感知夸张系数。
  4. view 连续拖动 fps 文本基于上一帧耗时估算(单帧 wall-clock 倒数), 非滑动平均, 数字会抖; 足够给用户感知量级(几十/几百 fps), 非精密基准(精密基准走 fps-budget/renderLOD 离屏)。
  5. last-metrics.txt(repo 根, 探针追加输出)未纳入提交——它从未被 git 跟踪, 是瞬时产物。