Есть ли способ сделать движущиеся / меняющиеся тени на Scenekit (как восходящее солнце)?
Мой основной код в значительной степени описан в этом руководстве: https://code.tutsplus.com/tutorials/an-introduction-to-scenekit-fundamentals--cms-23847
Я хочу сделать поведение на рассвете. Нечто подобное lightNode начинается на той же высоте, что и ограниченный cubeNode, и перемещает его вверх, чтобы тень со временем уменьшалась. Поэтому я попытался переместить узлы через SCNAction.move(в...).
Действие на lightNode -> ничего не происходит
Действие на ограниченном cubeNode -> тень начинает мерцать, но без изменений
Я пробовал с shadowModes. Я думаю, что я неправильно понял это. Никаких полезных результатов не получилось.
У кого-нибудь есть идея, если scenekit поддерживает что-то вроде динамического изменения теней?
2 ответа
Я нашел способ сделать это. Мои главные ошибки были:
Почему-то это не работает для доступа к lightNode (это просто не имеет никакого эффекта, когда действия для
lightNode
называются)Я пытался пройти через
SCNAction.move(to...)
, Ответ заключается в использовании вращения вместо продольного движения.
Ответом был доступ к узлу ограничения (вместо lightNode). В этом коде кубический узел заменяется невидимым centerPoint
(как узел ограничения, где lightNode
должен смотреть). boxNode
был добавлен для создания холста для тени. 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, как создать сложную загрузочную анимацию".
Но я не нашел способа изменить цвет тени. Это может быть хорошим эффектом иметь белые тени в ночное время и черные тени в дневное время. light.shadowColor
не помогло еще. Если у кого-то есть идея, это очень ценится.
Да. Вы можете сделать красивую движущуюся тень. Если ваш прожектор не движется, это может быть из-за того, что в руководстве вы наложили на него ограничение. Попробуйте удалить его.
// lightNode.constraints = [constraint]