首页 > 解决方案 > ARKit/SceneKit 阴影问题

问题描述

我正在开发适用于 iPhone 和 iPad 的 ARKit 应用程序,我在让阴影在相机的实时取景中工作时遇到了一些麻烦。我的场景 ( ShadowTest.scn) 如下所示:

场景图

我已取消选中RedGreenBlue和平面材料上Alpha的属性,并将可见性设置为。Write to ColorCull 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 视图

照明似乎正在工作,因为它已按应有的方式点亮。

我是否错过了使阴影出现所需的灯光/平面/立方体/场景视图上的一些非常明显的设置?

提前感谢您的所有帮助。

标签: iosswiftxcodescenekitarkit

解决方案


您应该能够在代码中执行此操作。试试这个:

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)
    
}

推荐阅读