布景
在体会HelloWorld时,很猎奇每个功用是怎样完成的,但是这个demo复用了很多功用、数据模型,刚开始了解起来就比较困难。所以我就先从功用点来看,将复用的功用、数据模型都剔除掉,保证单一功用能解藕独自运转。
环境
Xcode:15.1 beta
VisionOS:1.0
整理功用
graph LR;
功用点-->A(设置光照);
style A fill:#bbf,color:#fff
click A "https://www.6hu.cc/post/7298690615046651943"
功用点-->B(手势转动地球)
style B fill:#bbf,color:#fff
click B "https://www.6hu.cc/post/7298765809290706983"
功用点-->C(地球自转)
功用点-->D(地球跟从鼠标拖动)
功用点-->E(卫星围绕地球转动)
功用点-->F(月球围绕地球转动)
功用点-->G(沉溺式与窗口之间的切换)
设置光照
我是把官方demo中的功用独自拆分出来,便利学习。
![[VisionOS] 拆分HelloWorld的功用点 - 设置光照 [VisionOS] 拆分HelloWorld的功用点 - 设置光照](https://www.6hu.cc/wp-content/uploads/2023/11/6f39c00756a3812f35eaef3b693a0372.webp)
import SwiftUI
import RealityKit
import RealityKitContent
struct EarthSetSunlight: View {
@State var intensity: Float = 14
@State var showSunlight = false
@State var curEarth:Entity?
var body: some View {
ZStack{
RealityView { content in
guard let earth = await RealityKitContent.entity(named: "Earth") else {
return
}
content.add(earth)
earth.scale = SIMD3(repeating: 0.3)
curEarth = earth
} update: { content in
curEarth?.setSunlight(intensity: showSunlight ? intensity : 8)
}
Toggle("Sunlight", isOn: $showSunlight)
.toggleStyle(.button)
.padding(.top, 240)
}
}
}
#Preview {
EarthSetSunlight()
}
这段代码很简略,就是一个3D模型、一个切换开关,开关控制是否要设置光照。
这儿有两个知识点:
1. 加载3D资源
1.1 资源文件
1.1.1 直接拖HelloWorld里边的资源到自己的项目
![[VisionOS] 拆分HelloWorld的功用点 - 设置光照 [VisionOS] 拆分HelloWorld的功用点 - 设置光照](https://www.6hu.cc/wp-content/uploads/2023/11/1d0f946e6eda5d44e54e133477897cb9.webp)
![[VisionOS] 拆分HelloWorld的功用点 - 设置光照 [VisionOS] 拆分HelloWorld的功用点 - 设置光照](https://www.6hu.cc/wp-content/uploads/2023/11/2ae1c908f2590a84eb1b405cbd53f5f2.webp)
将所有的资源增加到自己的工程里边默许的RealityKitContent.rkassets
文件夹下面
1.1.2 自己创立
创立一个新的visionos
工程会自带一个3D资源。
![[VisionOS] 拆分HelloWorld的功用点 - 设置光照 [VisionOS] 拆分HelloWorld的功用点 - 设置光照](https://www.6hu.cc/wp-content/uploads/2023/11/e332d1ad019f189d86dc58b7d09acd9a.webp)
假如要修改资源,能够打开Package
,点击右上角Open in Reality Composer Pro
![[VisionOS] 拆分HelloWorld的功用点 - 设置光照 [VisionOS] 拆分HelloWorld的功用点 - 设置光照](https://www.6hu.cc/wp-content/uploads/2023/11/f124afb11fa670c578d1d7375bdbf968.webp)
打开后的样子
![[VisionOS] 拆分HelloWorld的功用点 - 设置光照 [VisionOS] 拆分HelloWorld的功用点 - 设置光照](https://www.6hu.cc/wp-content/uploads/2023/11/fdc0f10fe131d7b138e3a7e8faeb375b.webp)
在Reality Composer Pro
里边增加一个地球3D模型资源。
![[VisionOS] 拆分HelloWorld的功用点 - 设置光照 [VisionOS] 拆分HelloWorld的功用点 - 设置光照](https://www.6hu.cc/wp-content/uploads/2023/11/678015cac8304c69d8cfee18dd074da9.webp)
![[VisionOS] 拆分HelloWorld的功用点 - 设置光照 [VisionOS] 拆分HelloWorld的功用点 - 设置光照](https://www.6hu.cc/wp-content/uploads/2023/11/070578506782db689816557270132acb.webp)
双击资源,默许会把资源增加到Scene
,资源叫Earth.usdz
也能够拖动资源到下面的资源栏,这样就不属于任何scene。
![[VisionOS] 拆分HelloWorld的功用点 - 设置光照 [VisionOS] 拆分HelloWorld的功用点 - 设置光照](https://www.6hu.cc/wp-content/uploads/2023/11/6aeee4cb1a455d182b8a033fc7437bc6.webp)
假如不想放在原有的Scene
,就能够新建一个scene叫Earth
![[VisionOS] 拆分HelloWorld的功用点 - 设置光照 [VisionOS] 拆分HelloWorld的功用点 - 设置光照](https://www.6hu.cc/wp-content/uploads/2023/11/caf9bbfaf6ab820977da28f813f9eed4.webp)
将Earth.usdz
资源拖动到Earth
scene里边,就生成了一个Earth.usda
文件,这个就是后续RealityView
加载的资源。
![[VisionOS] 拆分HelloWorld的功用点 - 设置光照 [VisionOS] 拆分HelloWorld的功用点 - 设置光照](https://www.6hu.cc/wp-content/uploads/2023/11/ccbc75fa9fa37d0be66ca3ffe1254a5b.webp)
1.2 加载资源
目前加载3D资源,我这边统一用的是RealityKit
,往常我接触到的有两个Model3D
、RealityView
。
Model3D
更简略一点,拿来即用,就像加载Image一样。
RealityView
自定义的程度更高一些,主要用来展示Entity
的。能够修改资源Entity
,还能够在Entity
增加各种功用的组件Component
。还能够根据属性变化,来更新Entity
。
Entity
就是3D资源目标,能够改变它的大小、方位、旋转等,还能够增加各种功用的Component
,包括手势、碰撞、粒子作用、光照作用等。
2 增加光照
经过上面的介绍,光照其实就是一个功用Component
,增加到了3D资源目标上了。
2.1 光照资源
import SwiftUI
import RealityKit
extension Entity {
/// Adds an image-based light that emulates sunlight.
///
/// This method assumes that the project contains a folder called
/// `Sunlight.skybox` that contains an image of a white dot on a black
/// background. The position of the dot in the image dictates the direction
/// from which the sunlight appears to originate. Use a small dot
/// to maximize the point-like nature of the light source.
///
/// Tune the intensity parameter to get the brightness that you need.
/// Set the intensity to `nil` to remove the image-based light (IBL)
/// from the entity.
///
/// - Parameter intensity: The strength of the sunlight. Tune
/// this value to get the brightness you want. Set a value of `nil` to
/// remove the image based light from the entity.
func setSunlight(intensity: Float?) {
if let intensity {
Task {
guard let resource = try? await EnvironmentResource(named: "Sunlight") else { return }
var iblComponent = ImageBasedLightComponent(
source: .single(resource),
intensityExponent: intensity)
// Ensure that the light rotates with its entity. Omit this line
// for a light that remains fixed relative to the surroundings.
iblComponent.inheritsRotation = true
components.set(iblComponent)
components.set(ImageBasedLightReceiverComponent(imageBasedLight: self))
}
} else {
components.remove(ImageBasedLightComponent.self)
components.remove(ImageBasedLightReceiverComponent.self)
}
}
}
注释上说的很清楚了,就是Sunlight.skybox
文件夹下面有一个图片,图片黑色布景,有一个光点,光点就代表了光源的方位,物体的方位能够了解成是正中心。
![[VisionOS] 拆分HelloWorld的功用点 - 设置光照 [VisionOS] 拆分HelloWorld的功用点 - 设置光照](https://www.6hu.cc/wp-content/uploads/2023/11/0dc373c22d368077dca09180c1fbc146.webp)
![[VisionOS] 拆分HelloWorld的功用点 - 设置光照 [VisionOS] 拆分HelloWorld的功用点 - 设置光照](https://www.6hu.cc/wp-content/uploads/2023/11/c70d56d40252394b2f2cb6ecb5fb7c60.webp)
红色就表示我们要设置光照的方位,光点就是光源的方位,这儿就是光源在左边。
2.2 增加Component
Entity
目标能够增加多个Component,来完成不同的作用,这儿就增加的是ImageBasedLightComponent
、ImageBasedLightReceiverComponent
来完成光照。