VisionPro开发 - 轻松实现天空盒并添加光照


VisionPro开发系列首页:漫游Apple Vision Pro

系列项目全部代码:github.com/xuchi16/vis...


大家好,我是 xChester。

当我们希望给用户提供沉浸式体验时,常需要利用环境贴图构造天空盒。而 visionOS 本身不提供天空盒的功能,本文将实现一个简单的天空盒效果。

本文主要包含以下内容:

  • 简单的天空盒效果(Skybox),提供沉浸的体验

  • 为其中的物体添加基于图形的光照(Image Based Lighting,IBL),提供反射效果。

最终效果如下,可以看到沉浸式的天空和,同时其中的物体有相应的反射效果。

基本概念

HDRI(High Dynamic Range Imaging,高动态范围成像)环境贴图是一种提供详细光照信息的全景图像技术,用于在 3D 渲染和视觉效果中创建更加真实的光照和反射效果。

简单来说,当我们使用一张普通的全景图片作为环境贴图时,由于其中仅包含了拍摄时的曝光信息,当后续 3D 场景中渲染光照发生变化时图片中无论亮部还是暗部都会统一变化,如当光照变暗时,普通的图片会显得更"灰"。而相比于普通的全景图像,HDRI 图像在拍摄时就会对环境进行多次曝光,生成一系列曝光度不同的照片,并将它们合并成一个动态范围更广的图像。其中包含了更丰富的光照信息,包括色彩、亮度和反射细节等,在 3D 场景和模型的构建中能够营造更为真实的效果。

左。 HDR / 右。 JPG

IBL(Image Based Lighting)是一种在三维图形和视觉效果中使用的照明技术,通过使用 HDRI 图片来模拟光照,从而创造出更加真实和动态的视觉效果。RealityKit 就使用了 IBL 技术来模拟真实的反射效果。

主要步骤

  1. 获取 HDRI 资源并创建材质

  2. 创建模拟天空盒的球体并将 HDRI 贴图材质应用到天空盒上

  3. 加载 HDRI 资源并创建环境资源

  4. 创建环境中的物体并使用 IBL 光照

基本实现

获取 HDRI 资源并创建材质

PolyHeaven中找到想要的 HDRI 图片并下载,我们这里使用了一张上海外滩的夜景图。下载该图并导入 Xcode 项目中。利用如下代码

  1. 创建TextureResource
  2. 创建UnlitMaterial并使用上述贴图

UnlitMaterial是一种简单的材料,不会对环境中的其他光源做出响应。

swift 复制代码
guard let resource = try? await TextureResource(named: "shanghai_bund_4k") else {
    fatalError("Unable to load texture.")
}
var material = UnlitMaterial()
material.color = .init(texture: .init(resource))

创建天空盒球体

创建一个半径为 1000 的巨大球体,并将上述贴图应用到该球体上。另外,需要指定其 scale 的 x 方向为负,这样可以将贴图材质应用到球体的内表面。此时运行程序,我们仿佛已经置身上海外滩。

swift 复制代码
skybox.components.set(ModelComponent(
    mesh: .generateSphere(radius: 1000),
    materials: [material]
))

// Reverse x to let the picture applied to the inner side of skybox
skybox.scale = .init(x: -1 * abs(skybox.scale.x), y: skybox.scale.y, z: skybox.scale.z)

加载 HDRI 资源并创建环境资源

但如果此时在场景中添加物体,会发现物体并没有反射天空盒中的景色,呈现出黑色的无光照效果。

为了给物体添加 IBL 光照,仍需要使用刚刚的 HDRI 环境贴图。在 RealityKit 中,想要将该图用作 IBL 资源,需要

  1. 创建一个文件夹,并将其后缀改为.skybox

  2. 将 HDRI 文件放入上述文件夹中

  3. 将该文件夹拖到 Xcode 项目中,并选择"Create folder reference",将其添加到项目中

这样 Xcode 就能够将这张图片编译为环境资源,可以在代码中获取到该资源。

swift 复制代码
guard let environment = try? await EnvironmentResource(named: "shanghai_bund_4k") else {
    return
}

创建环境中的物体并使用 IBL 光照

创建一个球体,并将球体颜色设置为白色,isMetallic设置为ture,模仿光滑的金属表面,从而获得更好的反射效果。

swift 复制代码
let sphere = ModelEntity(
    mesh: .generateSphere(radius: 0.25),
    materials: [SimpleMaterial(color: .white, isMetallic: true)]
)

然后,创建一个ImageBasedLightComponent,通过该组件引用上述环境资源。再创建一个ImageBasedLightReceiverComponent作为关键光照的接收组件。将上述两组件应用到球体上,即可获得逼真的光照反射效果。

swift 复制代码
sphere.components.set(ImageBasedLightComponent(source: .single(environment)))
sphere.components.set(ImageBasedLightReceiverComponent(imageBasedLight: sphere))

最终效果

关注我

欢迎在掘金上关注我和我的专栏VisionOS Workshop,以及各种收藏/围观/评论/反馈/批评/Star/点歌

相关推荐
逐·風2 小时前
unity关于自定义渲染、内存管理、性能调优、复杂物理模拟、并行计算以及插件开发
前端·unity·c#
Devil枫2 小时前
Vue 3 单元测试与E2E测试
前端·vue.js·单元测试
尚梦3 小时前
uni-app 封装刘海状态栏(适用小程序, h5, 头条小程序)
前端·小程序·uni-app
GIS程序媛—椰子3 小时前
【Vue 全家桶】6、vue-router 路由(更新中)
前端·vue.js
前端青山4 小时前
Node.js-增强 API 安全性和性能优化
开发语言·前端·javascript·性能优化·前端框架·node.js
毕业设计制作和分享4 小时前
ssm《数据库系统原理》课程平台的设计与实现+vue
前端·数据库·vue.js·oracle·mybatis
2401_865854886 小时前
iOS应用想要下载到手机上只能苹果签名吗?
后端·ios·iphone
清灵xmf6 小时前
在 Vue 中实现与优化轮询技术
前端·javascript·vue·轮询
大佩梨6 小时前
VUE+Vite之环境文件配置及使用环境变量
前端
GDAL6 小时前
npm入门教程1:npm简介
前端·npm·node.js