Skip to content

Three.js 模型优化工程落地清单:指标对齐、体检门禁与自动优化

本文把两篇内容串成一条可执行的工程链路:

  • 性能指标口径与阈值:/thoughts/threejs/threejs-performance-panel-core-metrics-analysis
  • 模型优化策略与动作分层:/thoughts/threejs/threejs-model-optimization-comprehensive-solutions

目标是让项目从“上线后救火”变成“资产准入 + 自动策略 + 可观测验收”。

一、落地目标(必须明确)

  • 指标口径统一:面板展示、体检门禁、策略触发使用同一套指标与阈值分层
  • 优化前置:模型加载/解析完成后先体检,超标进入策略引擎,否则直接渲染
  • 安全优先:启用优化时优先安全优化;任何优化动作都不应被引擎强制默认开启,必须可配置、可回退、可按设备分层
  • 可观测闭环:每次加载的体检结果、触发动作、优化前后指标变化可追溯

二、工程模块拆分(建议按职责落地)

  • 体检统计(Stats Collector):从 glTF/Three.js 对象计算指标(Triangles/Textures/DC/Heap/VRAM 等)
  • 策略引擎(Policy Engine):根据设备档位与阈值,输出要执行的动作集合与顺序
  • 优化执行器(Optimizer):实现 Draco/合并几何体/实例化/减面/降纹理/LOD 等动作(可分插件)
  • 资源与缓存(Asset Cache):对优化产物做缓存与复用,避免重复优化
  • 可观测(Observability):指标上报、错误采集、策略命中率、优化收益统计

三、放在底座还是放在项目:边界建议(推荐分层)

不要把整套优化“全放项目层”或“全放底座层”,更推荐做成“底座提供能力 + 项目提供策略”的分层架构,既能统一口径复用能力,又能避免引擎层强行做业务不可接受的降级。

底座(引擎/框架层)建议负责:

  • 指标采集与口径:Triangles/Vertices/Textures/MaxTexture/Materials/DrawCall/FPS/Heap/VRAM Estimate
  • 可观测闭环:traceId、体检报告、动作耗时、优化前后对比与上报
  • 执行框架:Policy 接口、Optimizer 插件机制、缓存与幂等、开关与回退通道
  • 默认内置安全优化能力:例如 Draco/KTX2 解码支持、合并/实例化工具能力(但不强制启用)

项目(业务层)建议负责:

  • 设备档位与阈值:desktop/mobile 分层阈值与覆盖配置(与目标机型和画质目标强相关)
  • 资产规则:白名单/黑名单(哪些模型/贴图不能动,哪些允许有损)
  • 有损优化策略:减面/降纹理/通道精简/LOD 的触发条件与程度,以及画质验收与回退策略
  • 交互与拆分约束:拾取/高亮/分件动画等导致“合并几何体/实例化”不可用的规则

四、指标对齐(面板指标 → 体检门禁 → 策略触发)

核心原则:面板阈值用于诊断与提示;门禁阈值用于触发策略;二者同源,门禁通常略更严格,且移动端更严格。

建议以以下四类作为“策略触发主指标”(优先覆盖最大收益):

  • 三角面数(Triangles):GPU 算力压力
  • DrawCall(桌面/移动分档):CPU 提交压力
  • 纹理数量 + 最大纹理尺寸:显存/带宽压力
  • 显存估算(VRAM Estimate):闪退/黑屏风险

五、默认阈值(可直接落地的第一版)

指标触发(桌面)触发(移动)触发后优先动作
三角面数> 30 万> 15 万减面 / LOD
DrawCall> 300> 150合并几何体 / 实例化
纹理数量> 10> 8精简通道 / 复用 / 降纹理
最大纹理尺寸> 2048> 2048降纹理 / 纹理压缩
显存估算> 300 MB> 150 MB降纹理 / 精简通道 / 降级策略

六、指标到动作的映射(把“诊断”变成“可执行动作”)

指标异常常见根因可选动作(从上到下优先)关键取舍
三角面数高模型细节过密、无 LOD、重复几何未实例化实例化 → LOD → 适度减面画质 vs 算力
DrawCall 高mesh/材质碎片化、状态切换多合并几何体 → 材质收敛 → 实例化交互拆分 vs 合批收益
纹理数量多PBR 通道多、贴图重复、资产管理不规范复用/合图 → 精简通道 → 降纹理质感 vs 显存
最大纹理过大贴图分辨率过高、未压缩降纹理 → 纹理压缩(如 KTX2)清晰度 vs 显存/带宽
显存估算高纹理大/多、FBO/后处理重降纹理/压缩 → 精简通道 → 降级后处理体验一致性 vs 稳定性
JS Heap 高资源释放不当、缓存膨胀、重复加载资源回收 → 去重缓存 → 限制缓存上限复用效率 vs 内存
FPS 低综合超标优先排查 DrawCall 与纹理/三角面先抓大头

七、落地清单(按实施顺序)

6.1 第 1 步:统一指标口径与采集位置

  • GLTFLoader onLoad 后统一做体检统计,输出 ModelStats
  • 统计至少包含:triangles、drawCalls(估算)、textureCount、maxTextureSize、vramEstimate(估算)
  • 为每次加载生成 assetIdtraceId,将“体检结果 + 策略决策 + 动作执行结果”串起来

6.2 第 2 步:设备档位识别与阈值选择

  • 在运行时区分 deviceTier: desktop | mobile(第一版可仅按 UA/屏幕分辨率/内存粗分)
  • 允许通过配置覆盖阈值(项目可按目标机型调整)

6.3 第 3 步:策略引擎(输出动作列表)

  • 启用优化后建议动作序列为“安全优先”
    • Draco → 合并几何体 → 实例化 → 适度减面 → 降纹理 → LOD
  • 策略输出时必须带上原因:命中的指标、阈值与设备档位
  • 策略必须支持开关:
    • 全局开关:是否启用有损优化
    • 指标开关:是否对 triangles/texture/drawCall 单独启用策略

6.4 第 4 步:优化执行与缓存

  • 对执行器做幂等:同一 assetId + 策略版本 应命中缓存,避免重复优化
  • 对有损优化提供回退:优化后若画质不满足或收益不足,可退回到安全优化结果

6.5 第 5 步:面板与策略的闭环展示

面板建议增加三类信息,降低排查成本:

  • 体检摘要:triangles/drawCalls/textureCount/maxTextureSize/vramEstimate 的分档结果
  • 策略摘要:是否触发、触发原因、执行了哪些动作、耗时
  • 收益对比:优化前后关键指标变化(至少 triangles/drawCalls/纹理/显存估算)

6.6 第 6 步:验收标准(必须可量化)

  • 稳定性:移动端不闪退、不黑屏
  • 体验:目标机型 FPS 分档达到“正常”或以上,且波动可控
  • 成本:优化额外耗时有上限(例如策略执行总耗时、首屏可接受范围)
  • 质量:有损优化必须在可接受的画质阈值内(可用截图对比或主观评分)

6.7 第 7 步:灰度与回滚

  • 先灰度策略开关:按用户分组或按页面分组启用
  • 先启用安全优化:Draco/合并/实例化稳定后再逐步启用有损优化
  • 保留紧急开关:出现质量问题可一键关闭有损优化或全量策略

八、最小可用输出(MVP 交付清单)

  • ModelStats:triangles/textureCount/maxTextureSize/drawCalls/vramEstimate + deviceTier
  • PolicyEngine:阈值分层 + 动作列表输出 + 开关能力
  • Optimizer:至少实现 Draco + 合并几何体(或实例化)其中 1~2 个安全优化
  • 面板展示:体检摘要 + 策略摘要
  • 监控指标:策略触发率、优化耗时、优化收益(至少 2 项指标的前后对比)

九、可度量项清单(工程验收建议按此补齐)

这份清单覆盖了“最核心且普适”的可度量项,但不等同于“所有细节穷举”。不同业务形态(大场景/多模型/骨骼动画/后处理重)会引入额外度量项,建议把度量做成可扩展面板与事件上报。

8.1 资源与加载链路

指标口径建议采集位置用途
资源下载耗时TTFB + download请求层/Loader判断网络与 CDN 命中
解码/解析耗时Draco/KTX2 解码 + glTF parseLoader/Decoder判断 CPU 压力与 Worker 分配
首次可渲染时间从开始加载到首帧渲染完成应用层体验指标
缓存命中率assetId+策略版本命中比例Asset Cache判断“重复优化”是否被抑制

8.2 渲染压力(与性能面板对齐)

指标口径建议用途
Triangles/Vertices几何体统计GPU 算力压力
DrawCall/Materials渲染批次统计CPU 提交压力
Textures Count/Max Texture Size纹理统计显存/带宽压力
VRAM Estimate纹理解压体积近似 + 额外开销预留闪退/黑屏风险
FPS 与帧时间分位FPS + p50/p95/p99 frame time稳定性与卡顿定位
JS Heap 与 GC 频次Heap size + GC 次数/耗时卡顿与崩溃风险

8.3 策略与动作(必须可追溯)

指标口径建议用途
策略触发率触发次数/总加载次数判断阈值合理性
触发原因分布按指标超标维度聚合识别主要瓶颈
动作执行耗时每个动作耗时与失败率控制首屏成本
优化收益优化前后关键指标差值证明收益并迭代策略
回退比例回退次数/触发次数判断有损优化风险

8.4 画质与一致性(有损优化必须度量)

指标口径建议用途
画质分档人工评分/截图对比/像素差(可选)控制降级边界
关键资产白名单不允许降级的模型/贴图避免核心资产被误伤
设备分层策略命中desktop/mobile 分层的命中与收益验证分层合理性

十、优化动作权衡表(优缺点与适用边界)

这张表用于回答“为什么选这个动作、它的副作用是什么、什么时候不该用”。

动作主要收益主要代价/风险适用场景不适用/注意点
Draco下载与解析压力下降需要解码器,解码耗时增加大模型、网络瓶颈明显CPU 过弱设备需评估解码开销
合并几何体DrawCall 明显下降交互分件、材质/状态差异会限制合并mesh 碎片化、材质可收敛影响拾取/高亮/独立动画时需谨慎
实例化重复物体性能大幅提升每实例属性管理复杂同形多实例不同材质/不同几何不适用
适度减面Triangles 下降画质下降、法线细节损失GPU 算力瓶颈细节模型、近景资产需保守
降纹理VRAM/带宽下降显著文字/细节变糊显存瓶颈、移动端兜底UI/文字贴图需白名单或单独规则
贴图通道精简纹理数量与显存下降质感下降、塑料感质感要求可适当降低产品对真实感敏感时慎用
LOD远距离成本下降切换抖动、资源管理复杂大场景、远视距近景为主或切换不可接受时慎用

十一、安全优化是否会影响动画(必须提前设定边界)

“安全优化”通常指对外观影响小,但不等同于对语义/结构/动画完全无影响。尤其是“合并几何体、实例化”这类动作,可能会改变节点结构或渲染表达方式,从而影响动画与交互能力。

动作对骨骼动画(SkinnedMesh)对 Morph(变形)对节点级动画(平移/旋转/缩放)建议策略
Draco(几何压缩)基本不影响基本不影响不影响常作为首选动作,但仍建议默认关闭、由项目配置开启,并度量解码耗时
合并几何体高风险:跨 skin 合并会破坏绑定关系可能丢失或难以合并 morph targets高风险:丢失原节点层级与 pivot仅对静态、无骨骼/无 morph、且不依赖节点动画/分件交互的部分做合并
实例化通常不适用于 SkinnedMesh不适用或实现成本高节点动画需要改造成 per-instance 数据驱动仅对“同形多实例的静态网格”启用;动画物体优先用其他手段

工程落地时建议在体检统计里补充资产特征(例如:hasSkins、hasMorphTargets、hasNodeAnimations),并把它作为策略引擎的硬约束:命中这些特征时自动禁用合并/实例化,避免引入后续动画相关的复杂问题。

架构思考

把优化做成“体检门禁 + 策略引擎”后,团队协作会发生变化:讨论不再围绕某次卡顿的个案,而围绕“指标口径、阈值分层、策略命中与动作副作用”持续迭代。工程化的价值就在于把经验变成可配置、可度量、可回退的系统能力。