在使用
QLPreviewController
显示 .USDZ 模型时,我得到了开箱即用的接地阴影。然而,当我在 ARView
中加载相同的模型时,就没有这样的阴影了。为什么它被隐藏并且可以显示它吗? 或者我必须创建自定义阴影吗?
答案非常明显:由于
ARQuickLook
不允许您自定义场景中的任何内容(它是一个随时可用的解决方案),那么如果您想实现默认情况下在ARQuickLook
中激活的所有内容(可以是它的碰撞形状、手势、接地阴影、播放动画等)在 ARView
或 RealityView
中你必须实现这个从头开始。
RealityKit 4.0 (iOS 18.0+) 允许您从接收第一个实体阴影的另一个实体的角度生成
grounding shadows
。在 RealityKit 的早期版本中,您必须为此使用定向灯或聚光灯。
import SwiftUI
import RealityKit
struct ContentView : View {
var body: some View {
ARViewContainer().ignoresSafeArea()
}
}
struct ARViewContainer : UIViewRepresentable {
let arView = ARView(frame: .zero)
let anchor = AnchorEntity()
init() {
arView.environment.lighting.intensityExponent = 1.001
arView.environment.background = .color(.white)
}
func makeUIView(context: Context) -> ARView {
// Biplane's Entity
let entity = try! Entity.load(named: "biplane")
entity.position.y = 0.05
anchor.addChild(entity)
// Biplane's ModelEntity
let model = entity.findEntity(named: "toy_biplane_bind") as! ModelEntity
model.components[GroundingShadowComponent.self] =
.init(castsShadow: true,
receivesShadow: false)
// Shadow plane
let mesh = MeshResource.generatePlane(width: 0.5,
depth: 0.5,
cornerRadius: 0.25)
let material = SimpleMaterial()
let shadowPlane = ModelEntity(mesh: mesh, materials: [material])
shadowPlane.components[GroundingShadowComponent.self] =
.init(castsShadow: false,
receivesShadow: true)
anchor.addChild(shadowPlane)
arView.scene.anchors.append(anchor)
return arView
}
func updateUIView(_ view: ARView, context: Context) { }
}
这是某种跟踪的“VR 模式”(摄像头馈送被 ARView 的白色 BG 遮挡)。
对于 AR 模式,您可以使用
DirectionalLight
对象和捕捉阴影的非不透明材质,但由于某种原因 OcclusionMaterial
会导致表面“曝光过度”。我希望这个bug能够在未来的版本中得到修复。很可能有一些参数可以消除平面的“过度曝光的表面”效果,但我还没有找到。
struct ARViewContainer : UIViewRepresentable {
let arView = ARView(frame: .zero)
let anchor = AnchorEntity()
func makeUIView(context: Context) -> ARView {
// Biplane's Entity
let entity = try! Entity.load(named: "biplane")
entity.position.y = 0.05
anchor.addChild(entity)
// Light
let sun = DirectionalLight()
sun.shadow = .init()
sun.light.intensity = 4000
sun.light.color = .white
sun.orientation = .init(angle: -.pi/2, axis: [1,0,0])
anchor.addChild(sun)
// Shadow plane
let mesh = MeshResource.generatePlane(width: 0.5,
depth: 0.5,
cornerRadius: 0.25)
let material = OcclusionMaterial(receivesDynamicLighting: true) // !!!
let shadowPlane = ModelEntity(mesh: mesh, materials: [material])
anchor.addChild(shadowPlane)
arView.scene.anchors.append(anchor)
return arView
}
func updateUIView(_ view: ARView, context: Context) { }
}