Optimize your 3D assets for spatial computing
Spatial Computing 进阶 20m

为空间计算优化 3D 资产

Optimize your 3D assets for spatial computing

2024年6月10日

在 Apple 官方观看视频

一句话判断

如果你在做 visionOS 的 3D 内容,这场 Session 给出了 Apple Vision Pro 上从面数预算、纹理优化、材质设置到 IBL 定制的全套实践指南,数据具体到”10 万三角形是安全线”,干货密度很高。

这场 Session 讲了什么

Apple Vision Pro 的高分辨率显示和高帧率带来了极佳的用户体验,但也让 3D 内容的开发与传统平台有了本质区别。一个关键认知是:在 Vision Pro 上,GPU 只负责你实际渲染的像素,不负责透视视频(passthrough video)。这意味着 GPU 工作负载随你的 app 在用户视野中占据的面积而变化——非沉浸式场景可能快得多,而沉浸式场景每帧都要渲染数百万额外像素。

多边形数量是最重要的性能指标之一。Apple 给出的指导是:沉浸式场景建议不超过 50 万三角形,共享空间的应用建议不超过 25 万。一个更安全的指标是保持同时可见的三角形在 10 万左右,这能给你充足的性能余量。大型物体(如地形)应该分块处理,以便离屏时被剔除。

内容创作工具方面,Blender、Maya、Houdini 等都可以使用,关键是能导出 USD 格式。RealityKit 使用 Y 轴向上、-Z 轴向前的坐标系统,而 Blender 是 Z 轴向上、Y 轴向前,导出时需要注意这个差异。

纹理和材质部分涉及 Reality Composer Pro 的 Shader Graph。色彩空间的选择很重要:sRGB 用于感知类纹理(如基色),Linear 用于数据类或 HDR 纹理。Vision Pro 原生使用 Display P3 色域,但其他色域的纹理在 Xcode 构建时会自动转换。

值得深挖的点

USD 格式的三种变体各有适用场景

USD 不是单一格式,而是一个格式家族。USDA 是 ASCII 文本格式,适合协作和版本控制——Reality Composer Pro 用它作为场景格式正是因为它可以用文本工具解决合并冲突。USDC 是二进制格式,存储大量几何数据更高效,适合作为主要的资产交付格式。USDZ 是打包格式,把所有依赖(包括纹理)打包成内部文件结构,适合发布和分发,但不能直接编辑。

选择哪个格式取决于你的工作流阶段:创作过程中用 USDA 方便协作,构建管线中用 USDC 提高效率,最终分发用 USDZ。一个常见错误是在整个流程中都使用 USDZ——每次编辑都要解压再打包,效率很低。

纹理内存优化是一个系统工程

Session 中用了一个很实际的方法来优化纹理内存。灰度纹理(粗糙度、环境光遮蔽)不需要单独占用 RGB 通道——你可以把多个灰度纹理打包到一个 RGBA 图像的不同通道中。比如 R 通道存粗糙度,G 通道存金属度,B 通道存环境光遮蔽。这样一个纹理文件就能替代三个。

纹理压缩格式也很关键。ASTC 压缩是移动端 GPU 的标准选择,在质量和大小的权衡上表现出色。对于法线贴图,需要特别注意压缩格式——不当的压缩会导致法线方向出现块状伪影。建议对法线贴图使用更高的压缩质量设置,或者使用专门的法线贴图压缩模式。

代码片段

在 Reality Composer Pro Shader Graph 中设置纹理

// 在 Shader Graph 中添加纹理节点
// 1. 在 Project Browser 中导入纹理文件
// 2. 在材质的 Shader Graph 中添加 File Reference 节点
// 3. 选择纹理文件
// 4. 设置正确的 Color Space

// 基色纹理:sRGB - Display P3
// (感知类纹理,直接在渲染器中看到的颜色)
baseColorTexture.colorSpace = .sRGB_DisplayP3

// 粗糙度纹理:Linear - Display P3
// (数据类纹理,用于光照计算的数据)
roughnessTexture.colorSpace = .Linear_DisplayP3

// 通道打包:将多个灰度纹理合并
// R 通道 = 粗糙度
// G 通道 = 金属度  
// B 通道 = 环境光遮蔽
// 使用 Swizzle 节点分别提取各通道

场景:为 Vision Pro 的 3D 模型设置 PBR 材质。坑点:灰度纹理如果选了 sRGB 色彩空间,会导致光照计算不准确,因为 gamma 曲线会扭曲数据值。

从 Blender 导出 USD 时的坐标系统处理

# 在 Blender 中导出为 USDC 格式
import bpy

# 确保导出设置正确
bpy.ops.wm.usd_export(
    filepath="assets/scene.usdc",
    # 不导出材质(使用 Reality Composer Pro 的 Shader Graph)
    export_materials=False,
    # 导出几何数据
    export_meshes=True,
    # 注意:Blender 的坐标系统会自动转换
    # Y-up -> 需要在导入时旋转 -90 度 X 轴
)

场景:将 Blender 中创建的模型导入 Reality Composer Pro。坑点:坐标系统差异是最常见的导入问题——Blender 是 Z-up,RealityKit 是 Y-up。在 Reality Composer Pro 中给导入的资产应用 -90 度 X 轴旋转来修正。

Sky Dome 的高效设置

// Sky Dome 的纹理优化建议:
// 1. 使用 ASTC 压缩格式
// 2. 分辨率不需要太高——sky dome 距离远,细节不明显
// 3. 如果 sky dome 只用于 IBL 反射,
//    考虑直接使用 Image Based Lighting

// 在 Reality Composer Pro 中:
// 使用 Skybox 材质类型
// 关联一个 HDRI 环境贴图
// 设置为无限距离渲染

场景:为沉浸式场景创建天空背景。坑点:sky dome 的纹理分辨率过高会浪费大量内存,而用户几乎看不出区别——6144x3072 的 HDRI 对 sky dome 来说绰绰有余。

最佳实践

  • 在场景中放置一个 1.5m 高度的相机:帮助你判断内容从用户视角看的大小比例,避免资产过大或过小。
  • 分块处理大型几何体:地形等大型物体切分成小块,离屏部分可以被引擎剔除,显著降低实际渲染负担。
  • 灰度纹理打包到单张 RGBA 图像:三个灰度纹理合并为一个,节省三分之二的纹理内存。
  • 尽早测试资产导入:坐标系统和单位缩放问题越早发现越好,不要等到整个场景搭完才处理。
  • 理解色域和传递函数的区别:sRGB vs Linear 是传递函数(数据如何编码),Display P3 vs sRGB 是色域(颜色范围)。基色用 sRGB+P3,数据纹理用 Linear+P3。

还有什么值得关注

  • macOS Sequoia 的 Preview 应用新增了坐标系统和缩放的调整功能,不用打开 Reality Composer Pro 就能快速检查资产。
  • 《What’s new in USD and MaterialX》Session 有更多关于 USD 格式今年更新的内容。
  • Reality Composer Pro 的 Shader Graph 是设置材质的核心工具,2023 年的《Explore materials in Reality Composer Pro》是很好的入门材料。
WWDC 2024