[VisionOS] 拆分HelloWorld的功能点 - 设置光照

背景

在体验HelloWorld时,很好奇每个功能是怎么实现的,但是这个demo复用了很多功能、数据模型,刚开始理解起来就比较困难。所以我就先从功能点来看,将复用的功能、数据模型都剔除掉,保证单一功能能解藕单独运行。

环境

Xcode:15.1 beta

VisionOS:1.0

梳理功能

graph LR; 功能点-->A(设置光照); style A fill:#bbf,color:#fff click A "https://juejin.cn/post/7298690615046651943" 功能点-->B(手势转动地球) style B fill:#bbf,color:#fff click B "https://juejin.cn/post/7298765809290706983" 功能点-->C(地球自转) 功能点-->D(地球跟随鼠标拖动) 功能点-->E(卫星围绕地球转动) 功能点-->F(月球围绕地球转动) 功能点-->G(沉浸式与窗口之间的切换)

设置光照

我是把官方demo中的功能单独拆分出来,方便学习。

swift 复制代码
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,平常我接触到的有两个Model3DRealityView

Model3D更简单一点,拿来即用,就像加载Image一样。

RealityView自定义的程度更高一些,主要用来展示Entity的。可以编辑资源Entity,还可以在Entity添加各种功能的组件Component。还可以根据属性变化,来更新Entity

Entity就是3D资源对象,可以改变它的大小、位置、旋转等,还可以添加各种功能的Component,包括手势、碰撞、粒子效果、光照效果等。

2 添加光照

经过上面的介绍,光照其实就是一个功能Component,添加到了3D资源对象上了。

2.1 光照资源

Swift 复制代码
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,来实现不同的效果,这里就添加的是ImageBasedLightComponentImageBasedLightReceiverComponent来实现光照。

相关推荐
HarderCoder5 个月前
Apple Vision Pro 学习资料
visionos
苹果API搬运工5 个月前
试玩 RealityComposerPro 中的 Shader Graph:用圆环制作一个 Meta Logo
visionos·增强现实
苹果API搬运工5 个月前
我开源了个手势匹配框架,让你在模拟器调试 visionOS 手部追踪功能!
visionos·增强现实
苹果API搬运工5 个月前
只需三板斧!带你入门 visionOS 空间计算的数学与几何基础
visionos·增强现实
-九月新辰-6 个月前
Unity VisionOS开发流程
unity·游戏引擎·visionos
XR基地6 个月前
XR 世界导览021 | AVP App Store上线网页版、如何在AVP上快速匹配手势、AVP开发岗位
visionos
XR基地6 个月前
XR 世界导览#020-visionOS 1.1/Xcode 17.3/PICO 5.9.0 更新了!
unity3d·visionos
xChester6 个月前
visionOS 应用图标设计
前端·ios·visionos
XR基地6 个月前
XR 世界导览#019-Let's visionOS 大会/在 AVP 上玩手机或查看Spline的3D模型/用代码写ShaderGraph
unity3d·visionos
xChester7 个月前
VisionPro开发 - 轻松实现天空盒并添加光照
前端·ios·visionos