I've implemented one of the many ways to add a shadow plane to an ARKit and SceneKit scene. It works pretty well and the shadows look fine.
The problem is that most of the time the plane also has a grayish cast to it. In other words, it's not completely transparent. On the other hand, sometimes the grayish cast goes away only to reappear a few seconds later. I've tried tweaking just about every SCNNode and SCNMaterial property I can think of, but so far, I can't seem to get the gray to reliably go away. Does anyone have any suggestion on how to solve this?
// Make a transparent shadow plane for the Ground.
let shadowPlane = SCNPlane(width: CGFloat(self.width * 2), height: CGFloat(self.depth * 2))
shadowPlane.cornerRadius = 2
let shadowPlaneNode = SCNNode(geometry: shadowPlane)
shadowPlaneNode.name = shadowPlaneNodeName
shadowPlaneNode.eulerAngles.x = -.pi / 2
shadowPlaneNode.castsShadow = false
let material = SCNMaterial()
material.isDoubleSided = false
material.lightingModel = .constant // .shadowOnly does not show any shadows on iOS
material.colorBufferWriteMask = [.alpha]
shadowPlane.materials = [material]
node.addChildNode(shadowPlaneNode)
After more experimentation I found a solution that seems to be working well. Setting the material .lightingModel to .shadowOnly actually works correctly without any gray cast, but only if you set the .shadowModel on the shadow-producing direct light to .forward instead of .deferred.
In addition, I found that there seems to be a bug in .shadowOnly that causes the plane to be rendered completely black if there is any light in the scene with .type == .omni or == .spot.
Here's the code that's working for me:
let shadowPlane = SCNPlane(width: CGFloat(self.width * 1.5), height: CGFloat(self.depth * 1.5))
let shadowPlaneNode = SCNNode(geometry: shadowPlane)
shadowPlaneNode.name = shadowPlaneNodeName
shadowPlaneNode.eulerAngles.x = -.pi / 2
shadowPlaneNode.castsShadow = false
let material = SCNMaterial()
material.isDoubleSided = false
material.lightingModel = .shadowOnly // Requires SCNLight shadowMode = .forward and no .omni or .spot lights in the scene or material rendered black
shadowPlane.materials = [material]
node.addChildNode(shadowPlaneNode)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With