I have an AR
app in which I have calculated current sun position from the user. I reduced this position to distance of 10,000 meters
, so it kinda "stays" in place when I move inside the scene. Now I would like to cast shadows from this node on other nodes inside my scene. I tried few types of lightning, but none was successful. Some didn't drop shadow at all, others behave strange. What would be the best method to create a light source from such distant node to cast shadows on invisible floor node
? Should I also add ambient
light to the scene? Can it be added to camera node, or should be somewhere else?
1 Answers
Use directional
light for Sun simulation (Sun has parallel rays that for us are primary rays from very distant light source) and use ambient
light for simulating fake secondary rays (in case you do not use Global Illumination).
// DIRECTIONAL LIGHT for `primary light rays` simulation
let lightNode = SCNNode()
lightNode.light = SCNLight()
lightNode.light!.type = .directional
lightNode.light!.castsShadow = true
lightNode.light!.shadowMode = .deferred
lightNode.light!.categoryBitMask = -1
lightNode.light!.automaticallyAdjustsShadowProjection = true
//lightNode.light!.maximumShadowDistance = 11000
lightNode.position = SCNVector3(x: 0, y: -5000, z: 0)
lightNode.rotation = SCNVector4(x: -1, y: 0, z: 0, w: .pi/2)
scene.rootNode.addChildNode(lightNode)
Tip: The position of
directional
light could be any (in the following code it is even under the planey:-5000
), the most important thing is direction ofdirectional
light!Also
directional
light has nofalloff
parameter or, so called,quadratic light decay
.
// AMBIENT LIGHT for `fake secondary light rays` simulation
let ambientLightNode = SCNNode()
ambientLightNode.light = SCNLight()
ambientLightNode.light!.type = .ambient
ambientLightNode.light!.intensity = 1000
ambientLightNode.light!.color = NSColor.white
scene.rootNode.addChildNode(ambientLightNode)
Do not mistakenly use this Boolean value:
lightNode.castsShadow = true
instead of this one:
lightNode.light!.castsShadow = true
The Boolean value lightNode.castsShadow
determines whether SceneKit renders the node’s contents into shadow maps.
And here's a screenshot if you wish to enable shadows in manually created directional
light:
Sometimes, you get some benefits if you attach a light to the camera. In that case object's surfaces with normals parallel to light's rays are lit.