布景
在体会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中的功用独自拆分出来,便利学习。
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里边的资源到自己的项目
将所有的资源增加到自己的工程里边默许的RealityKitContent.rkassets
文件夹下面
1.1.2 自己创立
创立一个新的visionos
工程会自带一个3D资源。
假如要修改资源,能够打开Package
,点击右上角Open in Reality Composer Pro
打开后的样子
在Reality Composer Pro
里边增加一个地球3D模型资源。
双击资源,默许会把资源增加到Scene
,资源叫Earth.usdz
也能够拖动资源到下面的资源栏,这样就不属于任何scene。
假如不想放在原有的Scene
,就能够新建一个scene叫Earth
将Earth.usdz
资源拖动到Earth
scene里边,就生成了一个Earth.usda
文件,这个就是后续RealityView
加载的资源。
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
文件夹下面有一个图片,图片黑色布景,有一个光点,光点就代表了光源的方位,物体的方位能够了解成是正中心。
红色就表示我们要设置光照的方位,光点就是光源的方位,这儿就是光源在左边。
2.2 增加Component
Entity
目标能够增加多个Component,来完成不同的作用,这儿就增加的是ImageBasedLightComponent
、ImageBasedLightReceiverComponent
来完成光照。