有没有办法在 Scenekit 上制作 moving/changing 阴影(就像初升的太阳)?

Is there a way to make moving/changing shadows on Scenekit (like a rising sun)?

我的基本代码在该教程中几乎是这样的: https://code.tutsplus.com/tutorials/an-introduction-to-scenekit-fundamentals--cms-23847

我想做日出行为。诸如 lightNode 之类的东西从与受约束的 cubeNode 相同的高度开始并将其向上移动,以便阴影随着时间的推移变得更小。 因此我尝试通过 SCNAction.move(to...).

移动节点

对 lightNode 的操作 -> 什么都没有发生

作用在受约束的立方体节点上 -> 阴影开始闪烁,但没有变化

我尝试了 shadowModes。我想我误解了这一点。没有找到有用的结果。

有谁知道 scenekit 是否支持动态改变阴影之类的东西?

我找到了一种方法。我的主要错误是:

  1. 不知何故无法访问 lightNode(当调用 lightNode 的操作时,它只是没有效果)

  2. 我试图通过 SCNAction.move(to...)。答案是使用旋转而不是纵向移动。

答案是访问约束节点(而不是 lightNode)。在此代码中,cubeNode 被替换为不可见的 centerPoint(作为 lightNode 必须查看的约束节点)。添加了 boxNode 用于制作阴影 canvas。 lightNode 必须添加到 centerPoint,而不是场景。

有修改后的viewDidLoad方法。如果你想检查一下,打开 Xcode,启动一个新项目作为 SceneKit Game 并将 viewDidLoad 替换为以下代码。

    override func viewDidLoad() {
    super.viewDidLoad()

    // create a new scene
    let scene = SCNScene(named: "art.scnassets/ship.scn")!

    // create and add a camera to the scene
    let cameraNode = SCNNode()
    cameraNode.camera = SCNCamera()
    scene.rootNode.addChildNode(cameraNode)

    // place the camera
    cameraNode.position = SCNVector3(x: 0, y: 0, z: 15)

    // create and add a light to the scene
    let centerPoint = SCNNode.init()
    centerPoint.position = SCNVector3Make(0, 0, 0)
    scene.rootNode.addChildNode(centerPoint)

    let light = SCNLight()
    light.type = SCNLight.LightType.spot
    light.spotInnerAngle = 30
    light.spotOuterAngle = 80
    light.castsShadow = true
    light.color = UIColor.init(colorLiteralRed: 0.95, green: 0.8, blue: 0.8, alpha: 1)
    light.zFar = 200

    let lightNode = SCNNode()
    lightNode.light = light
    lightNode.position = SCNVector3Make(20, 100, 50)

    let constraint = SCNLookAtConstraint(target: centerPoint)
    constraint.isGimbalLockEnabled = true
    lightNode.constraints = [constraint]
    centerPoint.addChildNode(lightNode)

    let ambientLight = SCNLight.init()
    ambientLight.type = SCNLight.LightType.ambient
    ambientLight.color = UIColor.darkGray

    scene.rootNode.light = ambientLight

    // retrieve the ship node
    let material = SCNMaterial.init()
    material.diffuse.contents = UIColor.yellow
    material.lightingModel = SCNMaterial.LightingModel.phong
    material.locksAmbientWithDiffuse = true

    let boxNode = SCNNode.init(geometry: SCNBox.init(width: 10, height: 0.1, length: 10, chamferRadius: 0))
    boxNode.geometry?.firstMaterial = material
    boxNode.position = SCNVector3Make(0, -2, 0)

    scene.rootNode.addChildNode(boxNode)

    // animate spot light rotation
    centerPoint.runAction(SCNAction.repeatForever(SCNAction.rotateBy(x: CGFloat(M_PI), y: 0, z: CGFloat(M_PI), duration: 5)))

    // animate color light change
    let lightColorChange: CABasicAnimation = CABasicAnimation.init(keyPath: "color")
    lightColorChange.fromValue = UIColor.init(colorLiteralRed: 0.95, green: 0.8, blue: 0.8, alpha: 1)
    lightColorChange.toValue = UIColor.init(colorLiteralRed: 0, green: 0, blue: 0.4, alpha: 1)
    lightColorChange.duration = 5.0
    lightColorChange.autoreverses = true
    lightColorChange.repeatCount = Float.infinity
    light.addAnimation(lightColorChange, forKey: "changeLight")

    // retrieve the SCNView
    let scnView = self.view as! SCNView

    // set the scene to the view
    scnView.scene = scene

    // allows the user to manipulate the camera
    scnView.allowsCameraControl = true

    // show statistics such as fps and timing information
    scnView.showsStatistics = true

    // configure the view
    scnView.backgroundColor = UIColor.black

    // add a tap gesture recognizer
    let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))
    scnView.addGestureRecognizer(tapGesture)
}

这里也考虑了灯光的颜色变化。使用 CABasicAnimation 可以随时间更改 light.color-属性。它不像具有所有颜色阶梯的完美日出,但也有一种方法可以链接这些动画以使其更复杂。 (对于此搜索 "wenderlich how to create a complex loading animation".

但是我没有找到改变阴影颜色的方法。在夜间有白色阴影而在白天有黑色阴影可能是一个不错的效果。 light.shadowColor 还没有帮助。如果有人有想法,我们将不胜感激。

是的。你可以做出漂亮的移动影子。如果您的聚光灯没有移动,可能是因为教程对它施加了限制。尝试删除它。

// lightNode.constraints = [constraint]