【问题标题】:Issue with invisible Shadow Plane in SceneKit / ARKitSceneKit / ARKit中不可见的阴影平面问题
【发布时间】:2019-08-05 06:22:41
【问题描述】:

一段时间以来,我一直在四处寻找问题的答案,但找不到任何真正有帮助或解释正在发生的事情的东西。我也一遍又一遍地检查我在 SO 上找到的所有内容,但找不到答案。

在 AR 世界中显示对象时,该问题不断发生。 iEx 我将一个物体放在地板上的一个平面上,这是我的隐形阴影平面。然后,这完全取决于设备的视角。为了澄清,我添加了图像,它的视角略有不同。看看阴影发生了什么:

我希望一直有一个好的阴影,而不是像你看到的那样的人工制品。

注意:我已经尝试过使用 shadowSampleCount、Bias 和所有其他选项,它们应该有助于获得适当的、低渲染成本的阴影。

这里是Lighting和Plane、Material等相关代码的摘录

对于SCNLight

class func directionalLight() -> SCNLight {

    let light = SCNLight()

    light.type = .directional
    light.castsShadow = true
    light.color = UIColor.white
    light.shadowMode = .deferred
    light.shadowSampleCount = 8
    light.shadowRadius = 1
    // light.automaticallyAdjustsShadowProjection = false
    light.shadowColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.75)
    light.categoryBitMask = -1

    return light

}

以及我如何添加它:

func setupLights() {

    lightDirectionNode.light = Lighting.directionalLight()
    // lightDirectionNode.eulerAngles = SCNVector3(-66.degreesToRadians, 0, 0)
    lightDirectionNode.eulerAngles = SCNVector3(0, 90.degreesToRadians, 45.degreesToRadians)
    sceneView.scene.rootNode.addChildNode(lightDirectionNode)

}

对于SCNPlane

class func shadowPlane() -> SCNNode {

    let objectShape = SCNPlane(width: 200, height: 200)
    objectShape.heightSegmentCount = 2
    objectShape.widthSegmentCount = 2
    objectShape.cornerRadius = 100
    objectShape.cornerSegmentCount = 16

    let objectNode = SCNNode(geometry: objectShape)

    objectNode.geometry?.firstMaterial?.diffuse.contents = UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
    objectNode.geometry?.firstMaterial?.colorBufferWriteMask = SCNColorMask(rawValue: 0)

    objectNode.physicsBody = Physics.floorPhysicsBody(shape: objectShape)
    objectNode.name = "floor"
    objectNode.renderingOrder = -10 // renderingOrder // 0

    return objectNode
}

以及我如何添加它:

func setupShadowPlane() {

    let shadowPlane = NodeFactory.shadowPlane()

    // Set the Node's properties
    shadowPlane.position = SCNVector3(x: (focusSquare.lastPosition?.x)!, y: (focusSquare.lastPosition?.y)!, z: (focusSquare.lastPosition?.z)!)
    shadowPlane.eulerAngles = SCNVector3(-90.degreesToRadians, 0.0, 0.0)
    sceneView.scene.rootNode.addChildNode(shadowPlane)

}

我做错了什么?有人可以帮忙吗?

【问题讨论】:

    标签: swift scenekit augmented-reality arkit shadow


    【解决方案1】:

    还有 3 个实例属性需要考虑:

    var shadowRadius: CGFloat { get set }
    var shadowCascadeCount: Int { get set }
    var shadowCascadeSplittingFactor: CGFloat { get set }
    

    如果您不设置这些,它们肯定会导致渲染伪影。

    let lightNode = SCNNode()
    lightNode.light = SCNLight()
    // POSITION OF DIRECTIONAL LIGHT ISN'T IMPORTANT.
    // ONLY DIRECTION IS CRUCIAL FOR DIRECTIONAL LIGHTS.
    lightNode.rotation = SCNVector4(x: 0, y: 0, z: 0, w: 1)
    lightNode.light!.type = .directional
    lightNode.light!.castsShadow = true
    lightNode.light?.shadowMode = .deferred
    
    /* THREE INSTANCE PROPERTIES TO SETUP */
    lightNode.light?.shadowRadius = 3.25
    lightNode.light?.shadowCascadeCount = 3
    lightNode.light?.shadowCascadeSplittingFactor = 0.09
    
    lightNode.light?.shadowColor = UIColor(white: 0, alpha: 0.75)
    scene.rootNode.addChildNode(lightNode)
    

    还有一件事 – 当Auto Adjust 关闭时:

    Light 就像相机一样,具有 nearfar 剪切平面用于设置。

    lightNode.light?.zNear = 0
    lightNode.light?.zFar = 1000000    // Far Clipping Plane is important 
    

    希望这会有所帮助。

    【讨论】:

    • 这是正确答案。我在我的项目中对其进行了测试,结果被震撼了——就像魔术一样。
    猜你喜欢
    • 2021-07-08
    • 2021-02-19
    • 2020-09-25
    • 2020-05-06
    • 2016-06-11
    • 2018-03-21
    • 2018-01-12
    • 2017-11-17
    • 2023-03-10
    相关资源
    最近更新 更多