别被概念忽悠了,端侧 3D 重建是个技术活

今年 3DGS(3D Gaussian Splatting,3D 高斯泼溅)简直火得一塌糊涂。随便打开个技术社区,都在说“手机拍一圈,就能实时重建 3D 世界”。

听起来很酷对吧?很多同学热血沸腾,准备在 HarmonyOS 上大干一场。结果一搜教程,全是 Python、CUDA、甚至要几十张显卡的服务器集群。再一看手机,A 系列芯片算力再强,跟服务器比起来也是小巫见大巫。

在端侧做 3DGS,重建(训练)和渲染(显示)是两码事。

  • 端侧渲染:已经有个建好的 3DGS 模型(几十万个高斯球),要在手机屏幕上流畅跑 60 帧。这个可行,也是我们今天重点讲的。

  • 端侧重建:用手机拍几十张照片,直接算出高斯球的位置和颜色。这玩意儿极度吃算力,现阶段端侧做全流程重建,基本等于让小学生解微积分。

所以,这篇我们务实一点:聊聊怎么在 HarmonyOS 7 上渲染一个已建好的 3DGS 模型,以及端侧重建的边界在哪里。

https://placeholder-01.jpg/

一、渲染基础:别用 ArkUI,用 XComponent

想在 HarmonyOS 上做 3D 渲染,千万别在 ArkUI 层用普通的 Image 或者 Canvas。那玩意儿做点 2D 图表还行,做 3D,性能直接拉胯。

正确的姿势是:用 XComponent 结合 OpenGL ES 或者 ArkGraphics 3D。

XComponent 是 ArkUI 提供给开发者的底层渲染画布。你可以把它理解成一个可以让你自己操控 GPU 的窗口。

typescript

XComponent({
  id: 'xcomponent',
  type: XComponentType.SURFACE,
  libraryname: 'native_renderer'
})
.onLoad((context) => {
  // 表面加载完成
})
.onDestroy(() => {
  // 销毁
})

如果是用 C++ 写渲染逻辑,可以通过 libraryname 加载 native 库。如果纯 ArkTS 写,可以使用 @ohos.graphics.scene (ArkGraphics 3D 模块)。

对于 3DGS 来说,渲染的核心难点在于:高斯球不是传统的三角形网格(Mesh)。

传统的 3D 模型,是几千个三角形,GPU 处理起来驾轻就熟。而 3DGS 模型,是几十万甚至上百万个半透明的高斯球。每个球有自己的位置、缩放、旋转和透明度。

你要把这几十万个球渲染出来,就需要解决光栅化(Rasterization)和排序(Sorting)的问题。因为高斯球是半透明的,绘制顺序错了,重叠的部分颜色就会不对。

二、端侧优化:让几十万个高斯球跑出 60 帧

刚把模型加载进去,画面上可能只有 5 帧,手机烫得能煎蛋。怎么优化?

第一招:数据降采样。

别把所有高斯球都渲染出来。根据距离和屏幕占比,距离远、占比小的高斯球,直接剔除(Culling)。

typescript

// 伪代码:在顶点着色器或 CPU 侧做视锥体剔除
function cullGaussians(cameraPosition, gaussians) {
  return gaussians.filter(g => {
    // 距离太远的不要
    if (distance(cameraPosition, g.position) > MAX_DISTANCE) return false;
    // 屏幕占比太小的不要
    if (g.scale < MIN_SCALE) return false;
    return true;
  });
}

第二招:LOD(多细节层次)。

准备两套模型:一套高精度(近处看),一套低精度(远处看)。根据距离动态切换。

第三招:排序优化。

不要在 CPU 里每次渲染前都做一次全量排序。可以在初始化时就排好序,或者用 GPU 的基数排序(Radix Sort)来加速。

第四招:降分辨率渲染。

手机屏幕分辨率很高,如果你全分辨率渲染,压力太大。可以先在半分辨率下渲染,然后再上采样(Upscale)到全分辨率。虽然有点糊,但总比卡顿好。

https://placeholder-02.png/

三、端侧重建:手机拍一圈,真的能重建吗?

我们来看看端侧重建到底要经历什么。

  1. 特征提取:从几十张照片里找出关键点(SIFT/SuperPoint)。

  2. 位姿估计(SfM):算出每张照片是在哪个位置、什么角度拍的(COLMAP 干的事)。

  3. 稀疏重建:先建一个粗糙的点云。

  4. 稠密重建 / 3DGS 训练:把点云变成高斯球,并不断调整参数,让它和照片看起来一样。

在服务器上,第 4 步用 GPU 训练,可能只需要几分钟。但在手机端,没有强大的 GPU 加速,纯靠 CPU 和 NPU 去迭代几万次,可能需要几个小时,而且中途手机绝对会过热降频甚至闪退。

目前的行业共识是:

  • 手机端负责采集(多角度拍照/录像)和预处理(位姿估计)。

  • 重计算部分(3DGS 训练)传到云端或者边缘服务器。

  • 训练好的模型(高斯球数据)下发到端侧,手机只负责渲染和微调。

如果你的应用非要搞端侧重建,建议只做小物体重建(比如一个手办,放在桌面上,用台灯打光,拍个 20 张),并且把图像分辨率压得很低,否则你的应用一定会因为内存溢出和发热被用户卸载。

四、避坑合集:别在崩溃的边缘试探

坑一:加载模型时直接 OOM。

一个高精度的 3DGS 模型,包含几十万个高斯球,每个球有 59 个参数(位置、旋转、缩放、不透明度、球谐系数),数据量极大。直接全部读进内存,手机瞬间变砖。
解法:分块加载(Chunked Loading)。用户视角看到哪里,就加载哪里的高斯球数据。

坑二:半透明渲染顺序错乱,画面像一坨屎。

你必须严格按照从后往前的顺序绘制高斯球。如果乱序,叠加出来的颜色完全不对。
解法:使用深度排序(Depth Sorting),或者使用 OIT(Order Independent Transparency)技术。

坑三:手机发烫降频,帧率暴跌。

3D 渲染极度消耗 GPU 和内存带宽。
解法:限制帧率(比如锁 30 帧),降低渲染分辨率,离屏时立刻停止渲染循环。

https://placeholder-03.png/

五、总结

3DGS 是 3D 领域的未来,但在端侧落地,必须做出取舍。核心记住三点:

  1. 端侧重渲染,云端重训练,别在手机上硬扛训练任务。

  2. 用 XComponent 做 3D 渲染,别用普通的 ArkUI 组件。

  3. 剔除、降采样、排序,是保证 3DGS 在手机上流畅运行的三板斧。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐