Проблема с тенью ARKit / SceneKit

#ios #swift #xcode #scenekit #arkit

#iOS #swift #xcode #scenekit #arkit

Вопрос:

Я работаю над приложением ARKit для iPhone и iPad, и у меня возникли некоторые проблемы с получением теней для работы в режиме реального времени с камеры. Моя scene ( ShadowTest.scn ) выглядит следующим образом:

График сцены

Я снял флажок Red , Green , Blue , и Alpha для Write to Color свойства материала для плоскости, а также установил видимость Cull back .

Для направленного освещения Enable Shadows выбрано значение и установлен режим Deferred .

В самом файле сцены все выглядит хорошо. Тень видна, а плоскость — нет.

Моя проблема заключается в том, когда я добавляю ее в свой вид сцены. Вот как я добавляю его в свою сцену:

 func addTestBox(at position: SCNVector3, rotation: SCNVector4) {
    guard let scene = SCNScene(named: "Assets.scnassets/ShadowTest.scn") else {
        return
    }

    let node = SCNNode()

    scene.rootNode.childNodes.forEach(node.addChildNode(_:))

    node.position = position
    node.rotation = rotation

    updateQueue.async { [weak self] in
        self?.sceneView.scene.rootNode.addChildNode(node)
    }
}
  

Когда узлы добавляются в мою сцену, тень вообще не видна.

AR View без тени

Кажется, что освещение работает, потому что оно горит так, как должно быть.

Я пропускаю какую-то очень очевидную настройку в режиме освещения / плоскости / куба / сцены, которая необходима для отображения теней?

Спасибо в advanced за всю помощь.

Ответ №1:

Вы должны быть в состоянии сделать это в коде. Попробуйте это для освещения:

 func directionalLight() -> SCNLight {
    
    let light                           = SCNLight()
    light.type                          = .directional
    light.castsShadow                   = true
    light.color                         = UIColor.white
    light.shadowColor                   = UIColor(red: 0, green: 0, blue: 0, alpha: 0.75)
    light.shadowMode                    = .deferred
    light.shadowRadius                  = 2.0
    light.shadowCascadeCount            = 3
    light.shadowCascadeSplittingFactor  = 0.09
    light.shadowBias                    = 0.1
    light.shadowSampleCount             = 8 // (the smaller the value, the better the performance)
    light.categoryBitMask               = -1 // Shine on Everything

    return light
    
}
  

и это для материала:

 func shadowMaterialStandard() -> SCNMaterial {
    
    let material = SCNMaterial()
    
    
    material.diffuse.contents       = UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
    material.lightingModel          = .physicallyBased
    material.colorBufferWriteMask   = SCNColorMask(rawValue: 0)
    material.isLitPerPixel          = false
    material.isDoubleSided          = true
    
    
    return material
}
  

и это для SCNPlane (теневой плоскости):

 func setupShadowPlane() {
    
    let objectShape = SCNPlane(width: 50.0, height: 50.0)
    objectShape.heightSegmentCount = 1
    objectShape.widthSegmentCount = 1
    
    let objectNode = SCNNode(geometry: objectShape)
    objectNode.renderingOrder = -10 // for Shadow Material Standard
    objectNode.position = initialStartPosition
    objectNode.geometry?.firstMaterial = shadowMaterialStandard()
    objectNode.castsShadow = false // Important
    objectNode.eulerAngles = SCNVector3(-90.degreesToRadians, 0.0, 0.0)
    objectNode.name = "floor"
    objectNode.physicsBody = Physics.floorPhysicsBody(shape: objectShape)
    
    sceneView.scene.rootNode.addChildNode(objectNode)
    
}