# 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 --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 --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 ` —— 真窗口可交互(给用户肉眼测 + 最低配机跑) 实现要点: - 真 `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 [--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 `(肉眼判 fps≥30 + 交互流畅)或 `gpr_poc fps-budget ` (出该机体素-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 跟踪, 是瞬时产物。