2

This is the function that I use to display object on the plane surface.

private func loadScene(path: String) -> SCNNode {

    let spotLight = SCNLight()
    spotLight.type = SCNLight.LightType.probe

    spotLight.spotInnerAngle = 30.0
    spotLight.spotOuterAngle = 80.0
    spotLight.castsShadow = true

    let result = SCNNode()
    result.light = spotLight
    result.position = SCNVector3(-10.0, 20.0, 10.5)
    result.addChildNode(result)

    let scene = SCNScene(named: path)!
    for node in scene.rootNode.childNodes {
        result.addChildNode(node)
    }       
    return result
}

I want to display shadow on the plane surface like this image.

Image with Shadow on the plane surface

When I set spotlight type like below

spotLight.type = SCNLight.LightType.directional

It shows the object itself with light/dark shadow and does not drop the shadow on the surface.

Can someone please guide me how can I achieve the output as shown in the image?

Andy Jazz
  • 49,178
  • 17
  • 136
  • 220
  • 1
    Possible duplicate of [Can we render shadow on a transparent Plane in SceneKit](https://stackoverflow.com/questions/45505471/can-we-render-shadow-on-a-transparent-plane-in-scenekit) – mnuages Oct 10 '17 at 09:27

2 Answers2

5

// To Add Shadow on 3D Model Just Copy Paste this code and it will appear a shadow of 3D Model on Ground

let flourPlane = SCNFloor()
let groundPlane = SCNNode()
let groundMaterial = SCNMaterial()
groundMaterial.lightingModel = .constant
groundMaterial.writesToDepthBuffer = true
groundMaterial.colorBufferWriteMask = []
groundMaterial.isDoubleSided = true
flourPlane.materials = [groundMaterial]
groundPlane.geometry = flourPlane
//
mainNode.addChildNode(groundPlane)
// Create a ambient light
let ambientLight = SCNNode()
ambientLight.light = SCNLight()
ambientLight.light?.shadowMode = .deferred
ambientLight.light?.color = UIColor.white
ambientLight.light?.type = SCNLight.LightType.ambient
ambientLight.position = SCNVector3(x: 0,y: 5,z: 0)
// Create a directional light node with shadow
let myNode = SCNNode()
myNode.light = SCNLight()
myNode.light?.type = SCNLight.LightType.directional
myNode.light?.color = UIColor.white
myNode.light?.castsShadow = true
myNode.light?.automaticallyAdjustsShadowProjection = true
myNode.light?.shadowSampleCount = 64
myNode.light?.shadowRadius = 16
myNode.light?.shadowMode = .deferred
myNode.light?.shadowMapSize = CGSize(width: 2048, height: 2048)
myNode.light?.shadowColor = UIColor.black.withAlphaComponent(0.75)
myNode.position = SCNVector3(x: 0,y: 5,z: 0)
myNode.eulerAngles = SCNVector3(-Float.pi / 2, 0, 0)
// Add the lights to the container
mainNode.addChildNode(ambientLight)
mainNode.addChildNode(myNode)
// End
Akhzar Nazir
  • 724
  • 9
  • 13
  • I am used your code it's work but i am facing one issue. Some time shadow is not display at first time. If i am scale down or rotate object then shadow is appear. Do you have any idea why this happen ? – Mayuri R Talaviya Sep 05 '18 at 07:21
  • On iOS 13, you need to change `groundMaterial.colorBufferWriteMask = []` into `groundMaterial.colorBufferWriteMask = SCNColorMask.alpha` for it to work – Quang Tran Oct 01 '19 at 13:03
  • @QuangTran I change to `.alpha` but instead of shadow I have a big black plane!. How can i fix this? – iOS.Lover May 03 '20 at 05:14
  • @Mc.Lover try to recheck shadow color of direction light. Make sure it have an alpha value. – Quang Tran May 04 '20 at 06:40
  • @QuangTran I changed it to `groundMaterial.colorBufferWriteMask = .all` and worked – iOS.Lover May 04 '20 at 06:41
2

This edited version of the answer worked for me. I used material with shadowOnly model.

enter image description here

let flourPlane = SCNFloor()
let groundPlane = SCNNode()
let groundMaterial = SCNMaterial()
groundMaterial.lightingModel = .shadowOnly
flourPlane.materials = [groundMaterial]
groundPlane.geometry = flourPlane
//
node.addChildNode(groundPlane)
// Create a ambient light
let ambientLight = SCNNode()
ambientLight.light = SCNLight()
ambientLight.light?.shadowMode = .deferred
ambientLight.light?.color = UIColor.white
ambientLight.light?.type = SCNLight.LightType.ambient
ambientLight.position = SCNVector3(x: 0,y: 5,z: 0)
// Create a directional light node with shadow
let myNode = SCNNode()
myNode.light = SCNLight()
myNode.light?.type = SCNLight.LightType.directional
myNode.light?.color = UIColor.white
myNode.light?.castsShadow = true
myNode.light?.automaticallyAdjustsShadowProjection = true
myNode.light?.shadowSampleCount = 64
myNode.light?.shadowRadius = 16
myNode.light?.shadowMode = .deferred
myNode.light?.shadowMapSize = CGSize(width: 2048, height: 2048)
myNode.light?.shadowColor = UIColor.black.withAlphaComponent(0.75)
myNode.position = SCNVector3(x: 0,y: 1,z: -3)
myNode.eulerAngles = SCNVector3(-Float.pi / 2, 0, 0)
// Add the lights to the container
node.addChildNode(ambientLight)
node.addChildNode(myNode)
Ozgur Sahin
  • 1,305
  • 16
  • 24