How can I make shadows in RealityKit for USDZ files?

966 Views Asked by At

I use the code from this Medium story, but I didn't use RealityComposer. I added a simple sphere and plane on the anchor. But the result is weird, the sphere casts three lights but the plane has only spotLight. Another problem is I cannot see any shadows appeared.

Can anyone help? Thank you very much!

enter image description here

func session(_ session: ARSession, didAdd anchors: [ARAnchor]) {

    for anchor in anchors {

        let sphere = MeshResource.generateSphere(radius: 0.2)
        let simplemodel = ModelEntity(mesh: sphere, 
                                 materials: [SimpleMaterial(color: .white, 
                                                       isMetallic: false)])
        usdzEntity = simplemodel
        usdzEntity.generateCollisionShapes(recursive: true)

        // Plane primitive
        let plane: MeshResource = .generatePlane(width: 1.0,
                                                 depth: 1.0)
        let material = SimpleMaterial(color: .white,
                                 isMetallic: false)
        let entity = ModelEntity(mesh: plane,
                            materials: [material])
        usdzEntity.addChild(entity)

        usdzAnchorEntity = AnchorEntity(anchor: anchor)
        usdzAnchorEntity.addChild(usdzEntity)
        scene.addAnchor(usdzAnchorEntity)

        let lightAnchor = AnchorEntity(world: [0,0,-3])
        lightAnchor.addChild(directLight)
        lightAnchor.addChild(spotLight)
        lightAnchor.addChild(pointLight)
        scene.addAnchor(lightAnchor)
    }
}
1

There are 1 best solutions below

8
On

Lights in RealityKit have some peculiarities:

  • DirectionalLight()

    • Position is not important
    • Orientation is important
    • Has shadows
  • SpotLight()

    • Position is important
    • Orientation is important
    • Has shadows
  • PointLight()

    • Position is important
    • Orientation is not important
    • No shadows

enter image description here

Here's how these light types look in code:

@IBOutlet var arView: ARView!

override func viewDidLoad() {
    super.viewDidLoad()
    arView.backgroundColor = .black
    
    let directLight = DirectionalLight()
    directLight.light.color = .red
    directLight.light.intensity = 10000
    directLight.position.x = 0
    directLight.orientation = simd_quatf(angle: Float.pi/5,
                                          axis: [0, 1, 0])
    directLight.shadow = .init(DirectionalLightComponent.Shadow(maximumDistance: 5, 
                                                                      depthBias: 1))
    
    let spotLight = SpotLight()
    spotLight.light.color = .green
    spotLight.light.intensity = 450000
    spotLight.position.x = -1.1
    spotLight.shadow = .init()
    
    let pointLight = PointLight()
    pointLight.light.color = .blue
    pointLight.light.intensity = 700000
    pointLight.position.x = 3.0
    // pointLight has no shadows
    // pointLight's intensity is much higher than Directional's or Spot's one


    // SPHERE
    let sphere = MeshResource.generateSphere(radius: 0.4)
    let simpleModel = ModelEntity(mesh: sphere,
            materials: [SimpleMaterial(color: .lightGray,
                                  isMetallic: true)])
    let usdzEntity = simpleModel
    usdzEntity.generateCollisionShapes(recursive: true)

    // PLANE
    let plane: MeshResource = .generatePlane(width: 2.0,
                                             depth: 2.0)
    let material = SimpleMaterial(color: .lightGray,
                             isMetallic: false)
    let entity = ModelEntity(mesh: plane,
                        materials: [material])
    entity.orientation = simd_quatf(angle: Float.pi/4,
                                     axis: [1, 0, 0])
    usdzEntity.addChild(entity)

    let usdzAnchorEntity = AnchorEntity()
    usdzAnchorEntity.addChild(usdzEntity)
    arView.scene.addAnchor(usdzAnchorEntity)

    let lightAnchor = AnchorEntity(world: [0, 0, 2.5])
    lightAnchor.addChild(directLight)
    lightAnchor.addChild(spotLight)
    lightAnchor.addChild(pointLight)
    arView.scene.addAnchor(lightAnchor)
}