跳到主要内容

渲染架构与性能

本页解释 Viewer 为什么采用“后台准备、主线程创建场景、优先显示主体、描边可降级”的结构。它帮助你排查首帧、动画、光照或手势掉帧;它不是要求宿主直接操作 ArkGraphics 资源。

先看性能边界

组件负责宿主仍需避免
TaskPool 解析与面计划、Scene 代际取消、相机手势合并、延迟描边取消build() 中反复创建 Controller/Viewer;并发导入;在手势/Overlay 回调中做同步大 I/O;在 Viewer 外套竞争的双指手势

构建成功、日志无错误或缓存命中都不能代替真机帧率和首帧观察。尤其是 Component3D 的可见性、材质资源和双指手势,必须在目标机型验证。

JSON 导入管线

JSON 文本 / URI
→ UTF-8 大小与头部检查
→ TaskPool 解析 data[z][y][x]
→ 真实占用 bounds + 贪心面计划
→ ArkGraphics 主线程创建 Geometry / Material / Scene
→ 两阶段 Component3D 挂载
→ 可选载入动画
→ PBR 单位网格或兼容 BORD 描边

主线程不应逐体素生成网格,也不应在 build() 内创建新的 Scene。VoxelJsonScene 内部会按场景代际取消失效的动画和延后描边,避免旧模型的资源晚到新模型上。

为什么 surfaceCount 通常远小于体素数

相邻、同材质的可见体素面会被合并成较大的平面。这称为贪心表面合并:它不会改变方块的总体外形,但可以显著降低 Geometry 和三角形数量。因此 VoxelLoadResult.surfaceCount 是衡量渲染表面复杂度的一个可用指标,而不是每个方块的六面总数。

VFP 1.3 快速预览管线

Picker URI
→ Header / Footer / DIR0 随机读取
→ META + PAL0 + PMSH(及可选预览缓存)
→ TaskPool 转换紧凑面计划
→ ArkGraphics 创建最终表面
→ 与 JSON 相同的相机、光照、手势与动画路径

这条路径刻意跳过首帧的完整 VOX0/VBUF 读取,目标是“尽快可看”;它不是编辑准备,也不是 source hash 权威校验。

JSON 与 VFP 选择建议

资产来源建议入口原因
用户/AI 刚生成、需要人可读与调试JSON + loadText()/loadUri()直接从源数据生成表面。
已发布、大尺寸、反复查看VFP 1.3 + loadUri()可利用预览缓存和选择性 URI 读取。
要编辑或确认权威体素独立完整格式工具Viewer 的快速预览不是编辑准备。

贪心表面与单位描边

永久主体使用可见体素表面的贪心合并,减少 Geometry 与三角形数量。为了仍能看出单个体素边界,默认优先使用 PBR 材质内的单位网格纹理:

贪心表面 + Repeat UV + voxel_grid.png AO
→ 原始体素颜色不被覆盖
→ 描边随明暗面、光照和阴影变化

options.unitGridTexture = $rawfile('voxel/voxel_grid.png') 必须在首次加载前设置。静态 HAR 不能可靠在 ArkGraphics 内自行解析自身 rawfile Resource ID;宿主 Resource 可保证纹理创建。纹理不可用时才回退为独立 BORD Geometry,该路径会分批上传,首次描边更晚且对大模型更重。

首帧描边排查顺序

  1. 确认在第一次 load*() 前设置 options.unitGridTexture = $rawfile('voxel/voxel_grid.png')
  2. 确认资源路径由安装后的 HAR 依赖解析,而不是把宿主业务图片错误地传作单位网格。
  3. 在同一设备比较“有纹理”和“故意留空”两种情况;后者可能走兼容描边,不能拿来判断 PBR 路径性能。
  4. 若黑色体素的线过分明显,先检查 exposure、环境光和主光,再决定是否隐藏 voxelBordersVisible;不要通过叠加额外 Geometry 修补。

载入动画

  • 默认 STACK 是逐层堆砌;其余五种模式复用同一面计划,改变批次与路径。
  • 临时动画 Geometry 在视觉播放前创建并显式隐藏,避免“完整模型先闪现再播放”。
  • 播放期间输入被锁定;视觉结束时先恢复交互,临时资源再在后台释放。
  • 任何新加载、页面释放或场景代际变更都会通过版本号取消失效任务。

动画与交互的关系

载入动画不是把整个场景截图移动,而是按面计划控制显示批次。为了避免完整模型先闪现、动画中几何创建导致掉帧或相机和临时对象错位,组件会在动画期间忽略相机手势。动画结束后立即恢复控制;其后的资源回收不应阻塞相机,但仍应在真机连续拖动中检查。

性能优先级

  1. 正确且快速显示不透明主体。
  2. 动画期间保证帧连续,不在播放中提交大批原生 Geometry。
  3. 手势期间优先相机响应;描边可以稍后补齐。
  4. 编辑准备(不属于 HAR)必须和预览资源隔离,不能拖慢只读首帧。

容量建议

情况建议
128³ JSON 接近 15 MiB使用 loadUri(),让原始字节更早转交 TaskPool。
大型 VFP使用 VFP 1.3 + PMSH,并走 URI 选择性读取。
首帧缺描边检查 unitGridTexture,不要先调高边线 Geometry 批次。
手势掉帧检查宿主是否同步 rebuild 页面、套叠重手势或在回调里做 I/O。
内存压力降低业务侧同时保留的 JSON/VFP 副本;不要并发加载多个模型。

没有跨设备加载时间、FPS 或功耗承诺。任何性能改动都需要分别验证小模型、典型 128³ 模型、深浅背景、首帧、动画和连续双指操作。

渲染调参的安全顺序

  1. 从默认 VoxelRenderTuning 开始,关闭任何历史试验参数。
  2. 先调 exposurekeyIntensity,让主体在浅色/深色背景都能看清。
  3. 再调 ambientDiffusefillIntensityrimIntensity,保留方块不同面的明暗关系。
  4. 最后才考虑 Bloom、暗角、色散等气氛效果。
  5. 每次变更都测试彩色、低饱和和纯黑体素;纯黑资产最容易暴露描边/阴影比例问题。

完整字段和默认值见 VoxelViewer API 参考