HarmonyOS 6 ArkGraphics 3D精讲:从旋转立方体看鸿蒙原生3D能力

HarmonyOS 6 ArkGraphics 3D精讲:从旋转立方体看鸿蒙原生3D能力

前言:从数字孪生到鸿蒙 3D

大家好,我是你们老朋友木斯佳,熟悉我的朋友们知道,我长期从事物联网、数据可视化相关开发。过去几年里,我在各种平台上折腾过 3D 可视化:WebGL、Unity、自研引擎......也一直在关注鸿蒙在 3D 方向上的进展。

坦白说,在 HarmonyOS 6.0 之前,ArkGraphics 3D 的能力还比较单薄。那个时候:

  • 开发者主要能做的,是轻量化的模型展示
  • 真正稍微复杂一点的交互、渲染控制,往往要依赖 C API 去实现
  • 对于 ArkTS 开发者来说,3D 能力的门槛并不低

但从 HarmonyOS 6.0 开始,事情发生了本质变化。ArkGraphics 3D 的生产级体验大大增强:

  • 场景、节点、相机、材质、动画、后处理在 ArkTS 侧变得可组合、可控制
  • 轻 3D 场景不再需要绕过 UI 框架去单独维护
  • 渲染链路、资源管理、交互能力逐步形成工程闭环

作为长期在图形工程一线折腾的人,我对这种变化很敏感,也很兴奋。在实操过程中,从场景构建到骨骼动画,从坐标拾取到后处理,这条链路上的坑我基本都踩过一遍。这个专栏的目标,就是把我看到的这些变化、以及背后数学与图形在工程上的美学,用一篇一篇可落地的文章和你一起拆解。


一、3D界的Hello World:先搓一个能自转的立方体

3D 教程最怕上来就讲一堆名词,读完直接劝退。

3D界的Hello World,是渲染一个立方体。

在配套代码中,本篇案例的核心链路就是这几步:

ts 复制代码
Scene.load($rawfile('gltf/Cube/glTF/Cube.gltf'))
  .then(async (result: Scene) => {
    this.scene = result;
    this.sceneOpt = { scene: this.scene, modelType: ModelType.SURFACE } as SceneOptions;

    const rf = this.scene.getResourceFactory();
    this.camera = await rf.createCamera({ name: 'Article01Camera' });
    this.camera.enabled = true;
    this.camera.position.z = 4;

    this.cube = this.scene.getNodeByPath(Constants.CUBE_PATH);
    const greenMaterial = await rf.createMaterial(
      { name: 'Article01GreenMaterial' },
      MaterialType.METALLIC_ROUGHNESS
    );
    greenMaterial.baseColor = {
      image: null,
      factor: { x: 0.12, y: 0.74, z: 0.25, w: 1.0 }
    };
    (this.cube as Geometry).mesh.materialOverride = greenMaterial;
  });

让它动起来的部分也很直接:

ts 复制代码
const halfRadian = degree * Math.PI / 360;
this.cube.rotation = {
  x: 0,
  y: Math.sin(halfRadian),
  z: 0,
  w: Math.cos(halfRadian)
};

这段代码的意义很大。它是一个能把 场景加载、资源创建、相机、材质、节点旋转、组件绑定 串成闭环的原生 3D 能力。通过 ArkGraphics 3D 先能实现"模型加载"

只要这条链路通了,后面的坐标、旋转、场景图、资源、动画、灯光、相机和交互,才有继续讲下去的基础。


1.1 为什么旋转参数是 x, y, z, w?(四元数的"够用理解")

你可能会好奇:为什么旋转不是 rotation: { angle: 30, axis: 'y' },而是 x, y, z, w 四个值?

这是四元数 (Quaternion),图形学里处理旋转的标准方式。

直观理解(不深究数学):

  • 普通欧拉角 (x, y, z) 直观但有问题------万向锁 (Gimbal Lock):当两个旋转轴重叠时,会丢失一个旋转自由度
  • 四元数用 (x, y, z, w) 表示旋转,没有万向锁 ,且插值更平滑

在本例中:

ts 复制代码
// 绕 Y 轴旋转 degree 度
const halfRadian = degree * Math.PI / 360;
cube.rotation = {
  x: 0,                        // 不绕 X 轴
  y: Math.sin(halfRadian),     // 绕 Y 轴的分量
  z: 0,                        // 不绕 Z 轴
  w: Math.cos(halfRadian)      // 标量部分
};

后续我们会完整展开四元数与万向锁的介绍,这里先记住:看到 4 个旋转参数,别慌,那是为了更稳的旋转。


1.2 你可能遇到的第一批坑

在跑通这个立方体的过程中,你可能会遇到这些问题:

错误现象 原因 解决方案
画面全黑 相机未启用或位置不对 检查 camera.enabled = true,相机位置在物体前方
模型加载失败 glTF 路径错误或格式不兼容 确认文件在 rawfile 目录,使用官方示例模型测试
材质替换不生效 materialOverride 赋值时机不对 确保在 Scene.load.then 回调中执行
立方体不旋转 rotation 每帧未更新 使用 @StateaboutToAppear 中启动定时器/帧回调
旋转动画卡顿 每帧创建新对象 复用 cube 引用,不要重复 getNodeByPath
编译报错找不到 @kit.ArkGraphics3D 的类 SDK 版本低于 API 20 、或者是22、23更新时删除了一些旧的接口 检查 build-profile.json5 中的 compileSdkVersion

这些都是一些3D常见问题,如果你遇到类似情况,对照排查即可。


二、ArkGraphics 3D 是什么?

ArkGraphics 3D 可以理解成 鸿蒙系统里的一套原生 3D 图形能力

它的重点不是"做一个大而全的游戏引擎",而是把 3D 能力嵌进鸿蒙应用运行时里,让开发者能在 ArkUI 里直接:

  • 构建 3D 场景
  • 创建相机和光照
  • 绑定材质
  • 播放动画
  • 做射线检测(API 20+)

2.1 三个最核心的特征

特征 说明
轻量 不是 Unity / Unreal 那种重型引擎,而是让应用"够用、够快、够原生"
原生集成 不需要单独起引擎进程,Component3D 直接作为页面的一部分渲染
以渲染为中心 关注的是加载场景、管理节点、创建资源、控制相机、控制材质、渲染到屏幕

一句话:ArkGraphics 3D 适合在鸿蒙应用里需要 3D、但不想引入重型引擎的场景。

2.2 它适合什么?

场景 为什么适合
轻 3D 展示 不需要重型引擎,也能让产品快速 3D 化
电商商品展示 旋转、缩放、点击高亮、换材质都很实用
车载 HMI 系统级集成,和 UI 共存更自然
3D 特效卡片 可以把 3D 作为界面的一部分,而不是整页替换
工业 / 设备可视化 结构清晰,节点和资源关系容易管理

2.3 它不适合什么?

场景 适合程度 原因
大型动作游戏 ❌ 不适合 引擎生态、物理和工具链都不是这个方向
复杂刚体仿真 ❌ 不适合 不是以物理引擎为中心
超大场景开放世界 ❌ 不适合 不是重型游戏架构
需要强编辑器协作的 3D 生产管线 ⚠️ 视情况 需要结合工具链,不是纯引擎闭环

2.4 如果你熟悉 Unity 或 Three.js,这里是对照表

概念 Unity Three.js ArkGraphics 3D
场景根对象 Scene Scene Scene
游戏对象/节点 GameObject Object3D Node
相机 Camera Camera Camera
光源 Light Light Light
材质 Material Material Material
组件挂载 AddComponent<T>() add(object) 节点查找 + 属性修改
资源加载 Resources.Load() / Addressables GLTFLoader Scene.load() + ResourceFactory

关键差异 :ArkGraphics 3D 的 Node 没有像 Unity 那样的 AddComponent 模式,而是通过 getNodeByPath 查找后直接操作属性。这更接近场景图遍历的思路,而不是组件化组合。


三、HarmonyOS 6.0 前后:能力跃迁的关键分水岭

这是很多开发者容易忽略、但非常重要的一段背景。

3.1 HarmonyOS 6.0 之前

维度 状态
ArkTS 侧能力 偏轻量展示,深度控制有限
复杂交互 需要绕过框架,使用 C API
渲染控制 不灵活
对普通应用开发者 门槛偏高

3.2 HarmonyOS 6.0 之后

维度 状态
ArkTS 侧能力 场景 / 节点 / 材质 / 动画 / 后处理完整暴露
生产级体验 显著增强,可支撑业务落地
UI + 3D 融合 Component3D + ArkUI 原生打通
学习路径 更清晰,文档和示例逐步完善

本专栏的所有案例,都基于 HarmonyOS 6.0+ 的能力编写。

如果你还在更早的版本上做 3D,会明显感受到差异。


四、鸿蒙图形栈与渲染链路

你可以把鸿蒙 3D 的整体链路记成一句话:

text 复制代码
UI 层(ArkUI) → 方舟渲染层(ArkGraphics 3D) → 图形后端(Vulkan) → 显示

4.1 各层职责

层级 职责
ArkUI 页面、按钮、布局、文本、交互控件
ArkGraphics 3D 构建 3D 场景、组织渲染指令(Scene / Node / Camera / Light / Material)
Vulkan / OpenGL ES GPU 驱动层,真正执行渲染
显示 最终输出到屏幕

4.2 CPU 和 GPU 在 3D 里各做什么?

角色 负责内容 示例
CPU 调度员:加载资源、创建对象、处理交互、更新节点参数 Scene.load()cube.rotation = ...
GPU 工厂:顶点变换、光照计算、纹理采样、深度测试、像素输出 渲染管线执行

💡 为什么这件事重要?

很多 3D 卡顿不是"模型太大",而是:

  • 每帧重复创建资源
  • 不必要的重算
  • 过多的透明混合
  • 资源释放不及时

4.3 逃不开的坐标系:世界、局部、相机、屏幕

在 3D 世界里,一个顶点要经过 4 次坐标变换才能变成屏幕上的像素:

坐标系 说明 ArkGraphics 中的体现
局部坐标系 (Local) 模型自身的原点 glTF 文件内定义的顶点位置
世界坐标系 (World) 场景中的绝对位置 node.position
相机坐标系 (View) 相对于相机的坐标 camera.position + 朝向
裁剪/屏幕坐标系 (Projection/Screen) 最终输出的 2D 坐标 由相机投影矩阵自动计算

为什么这个重要?

当你要做射线检测(点击拾取物体)时,需要把屏幕坐标 (x, y) 反向变换回世界坐标系的射线。不理解这 4 层变换,交互就无从谈起。

后续会专门展开矩阵运算,这里先建立坐标系的概念框架。截止目前,鸿蒙官方并没有坐标系相关的辅助工具类,但是有盒模型相关工具类。后续我会带大家一一实现这些实用工具类,

4.4 一个旋转立方体,性能开销有多大?

实测(HarmonyOS 6.0,Mate 60 Pro):

指标 数值
帧率 稳定 60 FPS
CPU 占用 ~3% (单核)
GPU 占用 ~2%
内存增量 ~35 MB(含引擎开销)

这说明 ArkGraphics 3D 的基础渲染开销很低。后续当你加入复杂模型、多光源、阴影、后处理时,才是真正考验优化的开始。


五、案例一:旋转立方体的完整闭环

这一节是整篇文章的落地核心。配套代码做了几件很典型的事:

  1. 加载一个 glTF 立方体场景
  2. 创建相机
  3. 把 3D 场景挂到 Component3D
  4. 给立方体换一个更直观的绿色材质
  5. 每帧更新立方体四元数旋转

前置知识:我们加载的是什么?(glTF 简介)

本例加载的是 Cube.gltf。glTF 是 3D 模型的"JPEG 时代标准":

文件类型 说明 特点
.gltf (JSON) 描述场景结构、节点、材质、动画 可读,纹理单独存放
.glb (二进制) 上述内容打包成一个文件 体积小,适合网络传输

一个最简单的 glTF 包含:

  • meshes:顶点位置、法线、UV 坐标
  • nodes:层级关系、变换矩阵
  • materials:材质参数(PBR 工作流)
  • scenes:根场景引用

理解 glTF 结构,能帮你更好地理解 getNodeByPath 的路径从哪来。

5.1 完整代码链路解读

ts 复制代码
// ① 加载场景
Scene.load($rawfile('gltf/Cube/glTF/Cube.gltf'))
  .then(async (scene: Scene) => {
    // ② 获取资源工厂
    const rf = scene.getResourceFactory();

    // ③ 创建相机
    const camera = await rf.createCamera({ name: 'Article01Camera' });
    camera.enabled = true;
    camera.position.z = 4;

    // ④ 找到立方体节点
    const cube = scene.getNodeByPath(Constants.CUBE_PATH);

    // ⑤ 创建绿色材质
    const greenMaterial = await rf.createMaterial(
      { name: 'Article01GreenMaterial' },
      MaterialType.METALLIC_ROUGHNESS
    );
    greenMaterial.baseColor = {
      image: null,
      factor: { x: 0.12, y: 0.74, z: 0.25, w: 1.0 }
    };

    // ⑥ 替换材质
    (cube as Geometry).mesh.materialOverride = greenMaterial;
  });

5.2 逐 API 解读:每一行在做什么

代码 作用 注意事项
Scene.load($rawfile(...)) 异步加载 glTF 场景 返回 Promise,需要 await.then
scene.getResourceFactory() 获取资源工厂 用于创建相机、材质、光源等
rf.createCamera({ name }) 创建相机 需要设置 enabled = true 才会生效
camera.position.z = 4 设置相机位置 相机默认看向原点 (0,0,0)
scene.getNodeByPath(path) 按路径查找节点 路径取决于 glTF 内部结构
rf.createMaterial(name, type) 创建 PBR 材质 METALLIC_ROUGHNESS 是标准 PBR 工作流
material.baseColor.factor 设置基础色 RGBA 值范围 0~1,这里是绿色 (0.12, 0.74, 0.25)
mesh.materialOverride = material 替换材质 会覆盖 glTF 中的原始材质

5.3 这条链路教会你什么?

text 复制代码
Scene.load 
  → ResourceFactory 
    → Camera 
      → Node 
        → Material 
          → Component3D 
            → Rotation

只要能把这条链路看懂,才能真正理解能在鸿蒙页面里工作的 3D 场景体系。

六、传统 3D 概念的鸿蒙落点(速查表)

每个 ArkGraphics 3D 概念背后,都对应一个经典图形学概念。

传统 3D 概念 传统含义 ArkGraphics 3D 中的对应
场景图 管理物体层级关系 Scene + getNodeByPath()
相机 定义视角和投影 createCamera() + position
材质 表面外观属性 createMaterial() + baseColor
四元数 平滑旋转 rotation.x / y / z / w
glTF 3D 模型标准格式 Scene.load(.gltf)
MVP 矩阵 模型 → 世界 → 视图 → 投影 节点变换 + 相机参数

总结

如果你只带走一个结论,那就是:

ArkGraphics 3D 在鸿蒙 6.0 后已经可以对标老牌渲染体系的开发体验了。

它最适合做的,不是替代 Unity,而是在鸿蒙应用中补足 3D 表达和交互能力。

本篇的旋转立方体,只是一个入口。它证明的不是"我能渲一个方块",而是:

text 复制代码
场景加载 + 资源创建 + 相机 + 材质 + 节点更新 = 完整闭环

如果你已经跑通了第一个旋转立方体,后续我会带大家理解 ArkGraphics 里必须知道的那几个概念:坐标系、向量、矩阵、MVP。没有这些,后面的相机、光照、交互全都讲不透。

相关推荐
吃好睡好便好10 小时前
在Creo中如何把新建零件文件时的默认模板设置为公制单位
学习·3d·信息可视化
nashane11 小时前
HarmonyOS 6学习:PC端悬浮窗模式与智能长截图的协同优化实战
学习·华为·harmonyos
AI浩14 小时前
基于运动对齐RGB与事件视觉线索的无标签长时序3D无人机轨迹预测
3d·无人机
阿钱真强道15 小时前
23 鸿蒙LiteOS 消息队列(Queue)实战教程:任务间数据传递详解
harmonyos·鸿蒙·消息·队列·liteos·rk2206·瑞星微
前端不太难16 小时前
AI 不只是聊天框:鸿蒙 App 新入口
人工智能·状态模式·harmonyos
leon_teacher17 小时前
HarmonyOS 6 实战:基于 Ads Kit 的插屏广告(视频 + 图片)架构与实现全解析
架构·音视频·harmonyos
Hoxy.R17 小时前
银河麒麟 V10 离线安装 s3cmd 踩坑记录+存储负载均衡测试
linux·运维·华为·存储
大师兄666817 小时前
HarmonyOS 服务卡片开发之JS 卡片开发
javascript·华为·harmonyos·harmonyos6·formkit
程序猿追18 小时前
HarmonyOS 6.0 NEXT:基于 Map Kit 实现一款“手绘路线”骑行导航应用
华为·harmonyos