【问题标题】:casting shadow on invisible plane in Scenekit / ARkit在 Scenekit / ARkit 中的不可见平面上投射阴影
【发布时间】:2021-07-08 07:10:57
【问题描述】:

我发现很难在 scenekit 中的不可见平面上投射阴影,首先我试图在我的 AR 对象下创建一个不可见平面并在其上投射阴影,到目前为止都没有做到

我做对的一件事是我的对象在其他 AR 对象上有阴影,但在地面上没有(因为我认为我无法创建将投射阴影的不可见平面)

注意:我的项目使用的是苹果的演示项目代码

请帮助,在此先感谢

didAdd 节点委托

    func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
    guard let planeAnchor = anchor as? ARPlaneAnchor else { return }

    DispatchQueue.main.async {
        self.statusViewController.cancelScheduledMessage(for: .planeEstimation)
        self.statusViewController.showMessage("SURFACE DETECTED")
        if self.virtualObjectLoader.loadedObjects.isEmpty {
            self.statusViewController.scheduleMessage("TAP ON SCREEN TO PLACE AN OBJECT", inSeconds: 7.5, messageType: .contentPlacement)
        }
    }
    updateQueue.async {
        for object in self.virtualObjectLoader.loadedObjects {
            object.adjustOntoPlaneAnchor(planeAnchor, using: node)
        }
    }
}

didUpdate 节点委托

   func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
    guard let planeAnchor = anchor as? ARPlaneAnchor ,
          let planeNode = node.childNodes.first,let plane = planeNode.geometry as? SCNPlane else { return }
     
    // 2
    let width = CGFloat(planeAnchor.extent.x)
    let height = CGFloat(planeAnchor.extent.z)
    plane.width = width
    plane.height = height
     
    // 3
    let x = CGFloat(planeAnchor.center.x)
    let y = CGFloat(planeAnchor.center.y)
    let z = CGFloat(planeAnchor.center.z)
    planeNode.position = SCNVector3(x, y, z)
    updateQueue.async {
        for object in self.virtualObjectLoader.loadedObjects {
            object.adjustOntoPlaneAnchor(planeAnchor, using: node)
        }
    }
}

在其他物体上投射阴影

【问题讨论】:

    标签: ios swift augmented-reality scenekit arkit


    【解决方案1】:

    像这样尝试:

    阴影平面:

    func shadowPlane() -> SCNNode {
    
        let objectShape                    = SCNPlane(width: 30.0, height: 30.0)
        objectShape.heightSegmentCount     = 1
        objectShape.widthSegmentCount      = 1
    
        let objectNode                     = SCNNode(geometry: objectShape)
        objectNode.renderingOrder          = -10 // for Shadow Material Standard
        objectNode.position                = yourPosition
        objectNode.geometry?.firstMaterial = shadowMaterialStandard()
        objectNode.castsShadow             = false // Important
        objectNode.eulerAngles             = SCNVector3(CGFloat.pi/2, 0.0, 0.0)
        objectNode.name                    = "floor"
    
        return objectNode
    }
    

    对于材料:

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

    对于照明:

    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  // 3.25 // suggestion by StackOverflow
        light.shadowCascadeCount            = 3    // suggestion by StackOverflow
        light.shadowCascadeSplittingFactor  = 0.09 // suggestion by StackOverflow
        light.shadowBias                    = 0.1  // what's this?
        light.shadowSampleCount             = 8    // Quality of the Shadow - impacts performance when to high
        light.categoryBitMask               = -1   // Shine on Everything
    
        return light
    }
    
    func ambientLight() -> SCNLight {
    
        let light               = SCNLight()
        light.type              = .ambient
        light.color             = UIColor.white
        light.intensity         = 250
        light.categoryBitMask   = -1 // Shine on Everything
    
        return light
    }
    

    【讨论】:

    • 谢谢哥们
    • 如何在场景中添加灯光?就像我们添加其他节点一样添加到根节点?
    • 是的,将 SCNLight 添加到 SCNNode 的 .light 属性 - 就是这样。
    • 它不会在地面上投射任何阴影,有时它会看不见半个 AR 对象 .... :( ...你能告诉我添加平面和光线的适当方法吗到现场...如何处理 addNode 和 updateNode 委托?我可能在那里做错了什么:(
    • 如何分享,告诉我?我应该将您添加到 github 贡献者吗?
    猜你喜欢
    • 2019-08-05
    • 2017-12-12
    • 2018-01-05
    • 2018-03-21
    • 2020-09-25
    • 2018-06-20
    • 2017-07-09
    • 2015-06-29
    相关资源
    最近更新 更多