探索空间计算的渲染技术
Explore rendering for spatial computing
2023年6月5日
一句话判断
RealityKit 在空间计算平台上新增了自定义 IBL、Grounding Shadow、ShaderGraphMaterial 和可开关的 Tone Mapping——如果你要做 3D 内容渲染,这些是你控制视觉质量的关键工具。
这场 Session 讲了什么
Session 聚焦 RealityKit 在空间计算平台上的渲染能力,分为四个部分:
1. 光照与阴影:
- Image-Based Lighting(IBL):由 ARKit 提供的环境探针纹理 + 系统 IBL 纹理组合而成。系统 IBL 确保内容在任何环境下都好看。
- 自定义 IBL:新增
ImageBasedLightComponent和ImageBasedLightReceiverComponent,可以替换系统 IBL 用自定义环境光照亮 3D 内容。 - Grounding Shadow:让物体投射阴影到表面和物理环境上,帮助理解物体的空间位置。通过
GroundingShadowComponent并设置castsShadow = true启用。
2. 材质:
- 延续 iOS/macOS 的材质体系:PhysicallyBasedMaterial、SimpleMaterial、UnlitMaterial、VideoMaterial。
- 新增 ShaderGraphMaterial:在 Reality Composer Pro 中创作或从 MaterialX 文件加载。
- Tone Mapping:默认启用,将超过 1.0 的颜色值重新映射到可见范围,在高亮区域保留更多细节。
- 关闭 Tone Mapping:新增
applyPostProcessToneMap参数,设为 false 可以显示精确颜色——适合需要颜色与 SwiftUI UI 元素精确匹配的场景(如红绿灯 App)。
3. 光栅化率映射(Rasterization Rate Maps):
- 系统级性能优化,自动调整渲染分辨率。
- 根据用户注视的区域分配更多渲染资源。
- 开发者需要理解这个优化存在,确保内容在不同分辨率下都看起来好。
4. 动态内容缩放(Dynamic Content Scaling):
- 确保 UI 始终清晰锐利的技术。
值得深挖的点
Tone Mapping 的开关场景是一个容易忽略但很重要的选择。默认开启的 Tone Mapping 让材质在高亮区域保留更多细节——适合大多数 3D 场景。但如果你需要让 3D 内容的颜色与 SwiftUI UI 元素精确匹配(比如红绿灯的颜色要和按钮一致),Tone Mapping 会导致微小偏差。通过 applyPostProcessToneMap = false 关闭后,UnlitMaterial 的颜色输出与 SwiftUI 的颜色值完全一致。
Grounding Shadow 的价值在空间计算中比在 2D 屏幕上大得多。在 2D 屏幕上,物体的空间关系由透视和遮挡暗示。在空间计算中,一个浮在空中的 3D 物体如果没有阴影,用户很难判断它离桌面有多远。Grounding Shadow 提供了这个关键的深度线索——它投射在 3D 表面和真实物理环境上。
ShaderGraphMaterial 的引入让 RealityKit 的材质创作能力迈了一个台阶。之前只能通过代码参数控制材质,现在可以在 Reality Composer Pro 中用节点图的方式设计复杂材质。这对设计师和艺术家来说更友好——他们不需要写代码就能创建高级视觉效果。
代码片段
自定义 IBL 光照:
import RealityKit
// 加载 3D 模型和环境资源
let satellite = try await Entity(named: "satellite")
let sunEnvironment = try await EnvironmentResource(
named: "Sunlight" // 包含太阳和星空的环境贴图
)
// 创建自定义 IBL 组件
let iblComponent = ImageBasedLightComponent(
source: sunEnvironment
)
// 将 IBL 应用到实体
satellite.components.set(iblComponent)
// 让其他实体也使用同一个 IBL
let iblReceiver = ImageBasedLightReceiverComponent(
imageBasedLight: iblComponent
)
satellite.components.set(iblReceiver)
添加 Grounding Shadow:
// 加载模型
let vase = try await Entity(named: "flower_tulip")
// 添加投射阴影组件
var shadowComponent = GroundingShadowComponent()
shadowComponent.castsShadow = true // 启用阴影投射
vase.components.set(shadowComponent)
// 阴影会投射到 3D 表面和真实物理环境上
// 帮助用户理解物体在空间中的位置
关闭 Tone Mapping 以精确匹配颜色:
// 加载红绿灯模型
let trafficLight = try await Entity(named: "traffic_light")
// 找到红灯实体
let redLight = trafficLight.findEntity(named: "red_light")!
// 获取模型组件
var modelComponent = redLight.components[ModelComponent.self]!
// 创建关闭 Tone Mapping 的 UnlitMaterial
var material = UnlitMaterial(
color: .red,
applyPostProcessToneMap: false // 关键:关闭 tone mapping
)
// 应用材质——现在颜色与 SwiftUI 按钮精确匹配
modelComponent.materials = [material]
redLight.components[ModelComponent.self] = modelComponent
最佳实践
- 大多数场景使用系统 IBL 就足够了——只在需要特定光照氛围时才自定义 IBL。
- 放置在表面上的 3D 物体一定要加 Grounding Shadow,否则用户无法判断物体高度。
- 需要与 SwiftUI UI 颜色精确匹配的 3D 元素,用 UnlitMaterial + 关闭 Tone Mapping。
- ShaderGraphMaterial 在 Reality Composer Pro 中创作,不要试图纯代码构建复杂材质。
- 了解光栅化率映射的存在,确保内容在降低分辨率的区域仍然可读。
- 测试 3D 内容在不同光照环境下的表现——环境探针会影响材质的外观。
还有什么值得关注
- “Explore Materials in Reality Composer Pro” Session 详细介绍 ShaderGraphMaterial 的创作流程。
- Tone Mapping 对所有材质类型都默认开启,不只是 UnlitMaterial。
- 自定义 IBL 的环境资源可以用 HDR 照片或专用工具生成。
- 空间计算平台的渲染管线针对性能做了大量优化,开发者通常不需要手动管理渲染预算。
- PhysicallyBasedMaterial 仍然是最常用的材质类型,适合大多数真实世界物体的渲染。