perf(gpr_poc): view-all 概览每线单体 LOD,40 体→20 体修 1fps 卡顿

P11 cmdViewAll 每条线把 baseVolume(常驻底图)+hiresVolume(高清)两层都加进
renderer,20 线=40 体每帧 ray-cast,概览全可见(culled 0)→1.1fps。

改为每线只渲一个体:起步喂 baseImage()(粗 whole,小且不空,≤16384),引擎
按相机备好更合适 LOD 单图(currentImages)后整图换上 → 任何时刻每线 ≤1 体,
最多 20 体。视锥裁剪 toggle 唯一体可见性,拖动降采样保留,静止只渲就绪纹理
不重建。复用 ViewAdaptiveVolumeSource 引擎,未改库。

概览 1.1fps→42.98fps;体数 40→20(20 visible/0 culled);拉近 22.85fps
(17 visible/3 culled,视锥裁剪生效);无纹理维度错误,满帧非空白。
This commit is contained in:
gaozheng 2026-06-25 15:20:14 +08:00
parent 46f0144287
commit f52d38d97b
1 changed files with 32 additions and 45 deletions

View File

@ -4002,12 +4002,13 @@ struct PlacedSource {
vtkSmartPointer<vtkTransform> world; // TScale(1,1,exagg)→RotateZ→Translate vtkSmartPointer<vtkTransform> world; // TScale(1,1,exagg)→RotateZ→Translate
vtkSmartPointer<vtkTransform> worldInv; // T⁻¹相机逆变换到局部帧 vtkSmartPointer<vtkTransform> worldInv; // T⁻¹相机逆变换到局部帧
vtkSmartPointer<vtkVolumeProperty> prop; // 逐线 2/98 分位标定的传函(底图+高清共用) vtkSmartPointer<vtkVolumeProperty> prop; // 逐线 2/98 分位标定的传函
vtkSmartPointer<vtkVolume> baseVolume; // 常驻粗底图(永在场,套 T // P12每线只渲【一个】体不再底图层 + 高清层叠双渲20 线=40 体爆 1fps
vtkSmartPointer<vtkSmartVolumeMapper> baseMapper; // 该体输入由引擎按相机选的 LOD 决定:起步喂 baseImage()(粗 whole小且不空
vtkSmartPointer<vtkVolume> hiresVolume; // 高清叠加(就绪后局部覆盖,套 T // 引擎备好更合适的 currentImages() 后整图换上 → 任何时刻每线 ≤1 体 → 最多 20 体。
vtkSmartPointer<vtkSmartVolumeMapper> hiresMapper; vtkSmartPointer<vtkVolume> volume; // 唯一体(套 T
vtkSmartPointer<vtkImageData> currentImg; // 持当前高清单图引用mapper 仅持裸指针) vtkSmartPointer<vtkSmartVolumeMapper> mapper;
vtkSmartPointer<vtkImageData> currentImg; // 持当前单图引用mapper 仅持裸指针)
double worldBounds[6] = {0, 0, 0, 0, 0, 0}; // 该线(含 T+底图盒)的世界 AABB视锥裁剪用 double worldBounds[6] = {0, 0, 0, 0, 0, 0}; // 该线(含 T+底图盒)的世界 AABB视锥裁剪用
bool culled = false; // 本帧是否被视锥裁掉(两层皆隐 → 真跳过) bool culled = false; // 本帧是否被视锥裁掉(两层皆隐 → 真跳过)
@ -4082,17 +4083,16 @@ void viewAllSubmitOneLine(PlacedSource& ps, vtkCamera* worldCam,
1.0}); 1.0});
} }
// 非阻塞拉取该线后台已就绪的高清单图,喂高清 mapper无新结果→沿用上一帧 // 非阻塞拉取该线后台已就绪的引擎单图,换上唯一体的 mapper无新结果→沿用上一帧
// 返回 1=换上新图。 // 返回 1=换上新图。P12单体单层引擎选 LOD远→粗 whole近→细局部
int viewAllPickOneLine(PlacedSource& ps) { int viewAllPickOneLine(PlacedSource& ps) {
if (ps.culled) return 0; if (ps.culled) return 0;
auto imgs = ps.source->currentImages(); // 内部 takeLatest非阻塞 auto imgs = ps.source->currentImages(); // 内部 takeLatest非阻塞
if (imgs.empty() || imgs[0] == nullptr) return 0; if (imgs.empty() || imgs[0] == nullptr) return 0;
if (imgs[0] == ps.currentImg) return 0; if (imgs[0] == ps.currentImg) return 0;
ps.currentImg = imgs[0]; ps.currentImg = imgs[0];
ps.hiresMapper->SetInputData(ps.currentImg); ps.mapper->SetInputData(ps.currentImg);
ps.hiresMapper->Update(); ps.mapper->Update();
ps.hiresVolume->SetVisibility(1);
return 1; return 1;
} }
@ -4134,14 +4134,9 @@ void viewAllRefreshFrustum(ViewAllState* st) {
for (PlacedSource& ps : *st->lines) { for (PlacedSource& ps : *st->lines) {
const bool outside = aabbOutsideFrustum(ps.worldBounds, planes); const bool outside = aabbOutsideFrustum(ps.worldBounds, planes);
ps.culled = outside; ps.culled = outside;
ps.baseVolume->SetVisibility(outside ? 0 : 1); // P12每线唯一体。视锥外→隐真跳过 ray-cast可见→显并提交引擎目标局部帧
if (outside) { ps.volume->SetVisibility(outside ? 0 : 1);
ps.hiresVolume->SetVisibility(0); if (!outside) viewAllSubmitOneLine(ps, st->cam, st->aspect, st->viewportH);
} else {
// 可见:提交引擎目标(局部帧),高清可见性由 pick 决定(有就绪图才显)。
viewAllSubmitOneLine(ps, st->cam, st->aspect, st->viewportH);
ps.hiresVolume->SetVisibility(ps.currentImg != nullptr ? 1 : 0);
}
} }
} }
@ -4363,32 +4358,24 @@ int cmdViewAll(int argc, char** argv) {
ps.worldInv->DeepCopy(ps.world); ps.worldInv->DeepCopy(ps.world);
ps.worldInv->Inverse(); ps.worldInv->Inverse();
// 逐线传函(从常驻底图标定)+ 底图层 + 高清层,两层皆套世界变换 T。 // 逐线传函从常驻底图标定。P12每线只建【一个】体套世界变换 T
// 起步喂粗底图(小且不空),引擎备好更合适 LOD 单图后整图换上。
ps.prop = buildLineProperty(ps.meta, ps.source->baseImage()); ps.prop = buildLineProperty(ps.meta, ps.source->baseImage());
ps.baseMapper = vtkSmartPointer<vtkSmartVolumeMapper>::New(); ps.mapper = vtkSmartPointer<vtkSmartVolumeMapper>::New();
ps.baseMapper->SetRequestedRenderMode(vtkSmartVolumeMapper::GPURenderMode); ps.mapper->SetRequestedRenderMode(vtkSmartVolumeMapper::GPURenderMode);
ps.baseMapper->SetAutoAdjustSampleDistances(1);
ps.baseMapper->SetInteractiveAdjustSampleDistances(1);
ps.baseVolume = vtkSmartPointer<vtkVolume>::New();
if (ps.source->baseImage() != nullptr) {
ps.baseMapper->SetInputData(ps.source->baseImage());
ps.baseMapper->Update();
}
ps.baseVolume->SetMapper(ps.baseMapper);
ps.baseVolume->SetProperty(ps.prop);
ps.baseVolume->SetUserTransform(ps.world);
ps.hiresMapper = vtkSmartPointer<vtkSmartVolumeMapper>::New();
ps.hiresMapper->SetRequestedRenderMode(vtkSmartVolumeMapper::GPURenderMode);
// #1 拖动降采样:交互式采样距离自适应(拖动→大步长降采样跟手,松手→全质量)。 // #1 拖动降采样:交互式采样距离自适应(拖动→大步长降采样跟手,松手→全质量)。
ps.hiresMapper->SetAutoAdjustSampleDistances(1); ps.mapper->SetAutoAdjustSampleDistances(1);
ps.hiresMapper->SetInteractiveAdjustSampleDistances(1); ps.mapper->SetInteractiveAdjustSampleDistances(1);
ps.hiresVolume = vtkSmartPointer<vtkVolume>::New(); ps.volume = vtkSmartPointer<vtkVolume>::New();
ps.hiresVolume->SetMapper(ps.hiresMapper); if (ps.source->baseImage() != nullptr) {
ps.hiresVolume->SetProperty(ps.prop); ps.mapper->SetInputData(ps.source->baseImage());
ps.hiresVolume->SetUserTransform(ps.world); ps.mapper->Update();
ps.hiresVolume->SetVisibility(0); // 无就绪高清前不显(底图兜底) ps.currentImg = ps.source->baseImage(); // 起步即有图(不空白)
}
ps.volume->SetMapper(ps.mapper);
ps.volume->SetProperty(ps.prop);
ps.volume->SetUserTransform(ps.world);
// 该线世界 AABB底图模型盒经 T 变换的 8 角包络)→ 视锥裁剪用。 // 该线世界 AABB底图模型盒经 T 变换的 8 角包络)→ 视锥裁剪用。
if (ps.source->baseImage() != nullptr) { if (ps.source->baseImage() != nullptr) {
@ -4439,11 +4426,11 @@ int cmdViewAll(int argc, char** argv) {
vtkOutputWindow::SetInstance(capWin); vtkOutputWindow::SetInstance(capWin);
for (PlacedSource& ps : lines) { for (PlacedSource& ps : lines) {
ren->AddVolume(ps.baseVolume); // 先加底图 → 底层常渲 ren->AddVolume(ps.volume); // P12每线唯一体引擎 LOD 单层)
ren->AddVolume(ps.hiresVolume); // 后加高清 → 叠在底图上
} }
std::cout << "[view-all] 已加入场景线数=" << lines.size() std::cout << "[view-all] 已加入场景线数=" << lines.size()
<< "(底图常驻 + 高清叠加,各 ≤16384 单纹理,绝不撞 GL 纹理墙)\n"; << "(每线唯一体=" << lines.size()
<< " 体,引擎 LOD 单层,各 ≤16384 单纹理,绝不撞 GL 纹理墙)\n";
ViewAllState st; ViewAllState st;
st.lines = &lines; st.lines = &lines;