2

I am trying to add a shadow on SCNPlane, everything works fine but I cannot make SCNPlane transparent to show only the shadow not with the white background. here is the code:

        let flourPlane = SCNPlane()
        let groundPlane = SCNNode()


        let clearMaterial = SCNMaterial()
        clearMaterial.lightingModel = .constant
        //clearMaterial.colorBufferWriteMask = []
        clearMaterial.writesToDepthBuffer = true
        clearMaterial.transparencyMode = .default

        flourPlane.materials = [clearMaterial]

        groundPlane.scale = SCNVector3(200, 200, 200)
        groundPlane.geometry = flourPlane
        groundPlane.castsShadow = false
        groundPlane.eulerAngles = SCNVector3Make(-Float.pi/2, 0, 0)
        groundPlane.position = SCNVector3(x: 0.0, y: shadowY, z: 0.0)
        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 = .directional
        myNode.light?.castsShadow = true
        myNode.light?.automaticallyAdjustsShadowProjection = true
        myNode.light?.shadowSampleCount = 80
        myNode.light?.shadowBias = 1
        myNode.light?.orthographicScale = 1
        myNode.light?.shadowMode = .deferred
        myNode.light?.shadowMapSize = CGSize(width: 2048, height: 2048)
        myNode.light?.shadowColor = UIColor.black.withAlphaComponent(0.5)
        myNode.light?.shadowRadius = 10.0
        myNode.eulerAngles = SCNVector3Make(-Float.pi/2, 0, 0)
        node.addChildNode(ambientLight)
        node.addChildNode(myNode)

When I add clearMaterial.colorBufferWriteMask = [] shadow disappears! how can create a transparent material to show only the shadow.

enter image description here

The white area is SCNPlane and the red is the background.

iOS.Lover
  • 5,923
  • 21
  • 90
  • 162

2 Answers2

0

You can set materials "color" to .clear like below:

extension SCNMaterial {
convenience init(color: UIColor) {
    self.init()
    diffuse.contents = color
}
convenience init(image: UIImage) {
    self.init()
    diffuse.contents = image
}
}

let clearColor = SCNMaterial(color: .clear)
flourPlane.materials = [clearColor]
Abdul Karim Khan
  • 4,256
  • 1
  • 26
  • 30
0

I have found a trick in another SO answer.

Adjust the floor plane's blendMode to alter how its pixels are combined with the underlying pixels.

let clearMaterial = SCNMaterial()
// alter how pixels affect underlying pixels
clearMaterial.blendMode = .multiply
// use the simplest shading that shows a shadow (so not .constant!)
clearMaterial.lightingModel = .lambert
// unobstructed parts are render pure white and thus have no effect
clearMaterial.diffuse.contents = UIColor.white

floorPlane.firstMaterial = clearMaterial

You can see the effect in this image. The main plane is invisible, yet the shadow is visible. The cube, its shadow and the ball grid have the same XZ position. Notice how the "shadow" affects underlying geometries and the scene background.

Sample render of invisible plane with shadow

CloakedEddy
  • 1,965
  • 15
  • 27