到目前为止,我成功地从我的主
ImmersiveSpace
中打开了一个Window
,它将图像渲染为像这样的平面纹理。-
var body: some View {
ZStack {
RealityView { content in
var material = UnlitMaterial()
material.color = try! .init(tint: .white,
texture: .init(.load(named: "image",
in: nil)))
let entity = Entity()
let component = ModelComponent(
mesh: .generatePlane(width: 1, height: 1),
materials: [material]
)
entity.components.set(component)
entity.scale *= .init(x: 1, y: 1, z: 1)
let currentTransform = entity.transform
var newTransform = Transform(scale: currentTransform.scale,
rotation: currentTransform.rotation,
translation: SIMD3(0, 0, -0.3))
entity.move(to: newTransform, relativeTo: nil)
/*
let scalingPivot = Entity()
scalingPivot.position.y = entity.visualBounds(relativeTo: nil).center.y
scalingPivot.addChild(entity)
content.add(scalingPivot)
scalingPivot.scale *= .init(x: 1, y: 1, z: 1)
*/
}
}
}
但我无法将其移到
z-axis
深处以将其显示在窗口后面(如果我设置的值小于-0.4,它就会消失)。
此外,我尝试了多种缩放方式,以便背景图像显示得比窗口大,但任何缩放操作似乎只影响纹理坐标,而不影响平面网格本身。
最后,我希望理想地在曲面中渲染此图像(非常类似于 180% 全景图像)。作为第一种方法,我找到了 this 教程来创建弯曲的墙,但似乎箭头对象在
Reality Composer Pro
上不再可用。
也欢迎任何关于在主窗口后面渲染背景图像的不同方法的建议/提示:)
如果您在
ImmersiveSpace
,您可以使用 Apple 的“DestinationVideo”中的 addSkybox
在您的
App
文件中
@main
struct SimpleVideoPlayerApp: App {
@Environment(\.openImmersiveSpace) var openImmersiveSpace
var body: some Scene {
WindowGroup {
Text("Hello World!")
}
ImmersiveSpace(id: "ImmersiveSpace") {
SkyboxView()
}.immersionStyle(selection: .constant(.progressive), in: .progressive)
}
}
然后在另一个文件中
#if os(visionOS)
import SwiftUI
import RealityKit
import Combine
struct SkyboxView: View {
var body: some View {
RealityView { context in
let entity = Entity()
entity.addSkybox(for: "beach_scene", rotation: .degrees(55))
context.add(entity)
}
}
}
extension Entity {
func addSkybox(for name: String, rotation: Angle) {
let subscription = TextureResource.loadAsync(named: name).sink(
receiveCompletion: {
switch $0 {
case .finished: break
case .failure(let error): assertionFailure("\(error)")
}
},
receiveValue: { [weak self] texture in
guard let self = self else { return }
var material = UnlitMaterial()
material.color = .init(texture: .init(texture))
self.components.set(ModelComponent(
mesh: .generateSphere(radius: 1E3),
materials: [material]
))
self.scale *= .init(x: -1, y: 1, z: 1)
self.transform.translation += SIMD3<Float>(0.0, 1.0, 0.0)
// Rotate the sphere to show the best initial view of the space.
print("rotate")
updateRotation(for: rotation)
}
)
components.set(Entity.SubscriptionComponent(subscription: subscription))
}
func updateRotation(for rotation: Angle) {
// Rotate the immersive space around the Y-axis set the user's
// initial view of the immersive scene.
let rotation = simd_quatf(angle: Float(rotation.radians), axis: SIMD3<Float>(0, 1, 0))
self.transform.rotation = rotation
}
/// A container for the subscription that comes from asynchronous texture loads.
///
/// In order for async loading callbacks to work we need to store
/// a subscription somewhere. Storing it on a component will keep
/// the subscription alive for as long as the component is attached.
struct SubscriptionComponent: Component {
var subscription: AnyCancellable
}
}
https://developer.apple.com/documentation/visionos/destination-video