在 Scenekit / ARkit 中的不可见平面上投射阴影
casting shadow on invisible plane in Scenekit / ARkit
我发现很难在 scenekit 中的不可见平面上投射阴影,首先我试图在我的 AR 对象下创建一个不可见平面并在其上投射阴影,到目前为止未能做到这两个
我做对的一件事是我的对象在其他 AR 对象上有阴影但在地面上没有(因为我认为我无法创建将投射阴影的不可见平面)
注意:我在我的项目中使用了苹果的演示项目代码
请帮忙,提前致谢
didAdd节点委托
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
guard let planeAnchor = anchor as? ARPlaneAnchor else { return }
DispatchQueue.main.async {
self.statusViewController.cancelScheduledMessage(for: .planeEstimation)
self.statusViewController.showMessage("SURFACE DETECTED")
if self.virtualObjectLoader.loadedObjects.isEmpty {
self.statusViewController.scheduleMessage("TAP ON SCREEN TO PLACE AN OBJECT", inSeconds: 7.5, messageType: .contentPlacement)
}
}
updateQueue.async {
for object in self.virtualObjectLoader.loadedObjects {
object.adjustOntoPlaneAnchor(planeAnchor, using: node)
}
}
}
didUpdate 节点委托
func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
guard let planeAnchor = anchor as? ARPlaneAnchor ,
let planeNode = node.childNodes.first,let plane = planeNode.geometry as? SCNPlane else { return }
// 2
let width = CGFloat(planeAnchor.extent.x)
let height = CGFloat(planeAnchor.extent.z)
plane.width = width
plane.height = height
// 3
let x = CGFloat(planeAnchor.center.x)
let y = CGFloat(planeAnchor.center.y)
let z = CGFloat(planeAnchor.center.z)
planeNode.position = SCNVector3(x, y, z)
updateQueue.async {
for object in self.virtualObjectLoader.loadedObjects {
object.adjustOntoPlaneAnchor(planeAnchor, using: node)
}
}
}
在其他物体上投射阴影
试试看:
阴影平面:
func shadowPlane() -> SCNNode {
let objectShape = SCNPlane(width: 30.0, height: 30.0)
objectShape.heightSegmentCount = 1
objectShape.widthSegmentCount = 1
let objectNode = SCNNode(geometry: objectShape)
objectNode.renderingOrder = -10 // for Shadow Material Standard
objectNode.position = yourPosition
objectNode.geometry?.firstMaterial = shadowMaterialStandard()
objectNode.castsShadow = false // Important
objectNode.eulerAngles = SCNVector3(CGFloat.pi/2, 0.0, 0.0)
objectNode.name = "floor"
return objectNode
}
对于Material:
func shadowMaterialStandard() -> SCNMaterial {
let material = SCNMaterial()
material.colorBufferWriteMask = SCNColorMask(rawValue: 0) // important
material.diffuse.contents = UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
material.lightingModel = .physicallyBased // OK
material.isDoubleSided = true
return material
}
对于照明:
func directionalLight() -> SCNLight {
let light = SCNLight()
light.type = .directional
light.castsShadow = true
light.color = UIColor.white
light.shadowColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.75)
light.shadowMode = .deferred
light.shadowRadius = 2.0 // 3.25 // suggestion by Whosebug
light.shadowCascadeCount = 3 // suggestion by Whosebug
light.shadowCascadeSplittingFactor = 0.09 // suggestion by Whosebug
light.shadowBias = 0.1 // what's this?
light.shadowSampleCount = 8 // Quality of the Shadow - impacts performance when to high
light.categoryBitMask = -1 // Shine on Everything
return light
}
func ambientLight() -> SCNLight {
let light = SCNLight()
light.type = .ambient
light.color = UIColor.white
light.intensity = 250
light.categoryBitMask = -1 // Shine on Everything
return light
}
我发现很难在 scenekit 中的不可见平面上投射阴影,首先我试图在我的 AR 对象下创建一个不可见平面并在其上投射阴影,到目前为止未能做到这两个
我做对的一件事是我的对象在其他 AR 对象上有阴影但在地面上没有(因为我认为我无法创建将投射阴影的不可见平面)
注意:我在我的项目中使用了苹果的演示项目代码
请帮忙,提前致谢
didAdd节点委托
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
guard let planeAnchor = anchor as? ARPlaneAnchor else { return }
DispatchQueue.main.async {
self.statusViewController.cancelScheduledMessage(for: .planeEstimation)
self.statusViewController.showMessage("SURFACE DETECTED")
if self.virtualObjectLoader.loadedObjects.isEmpty {
self.statusViewController.scheduleMessage("TAP ON SCREEN TO PLACE AN OBJECT", inSeconds: 7.5, messageType: .contentPlacement)
}
}
updateQueue.async {
for object in self.virtualObjectLoader.loadedObjects {
object.adjustOntoPlaneAnchor(planeAnchor, using: node)
}
}
}
didUpdate 节点委托
func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
guard let planeAnchor = anchor as? ARPlaneAnchor ,
let planeNode = node.childNodes.first,let plane = planeNode.geometry as? SCNPlane else { return }
// 2
let width = CGFloat(planeAnchor.extent.x)
let height = CGFloat(planeAnchor.extent.z)
plane.width = width
plane.height = height
// 3
let x = CGFloat(planeAnchor.center.x)
let y = CGFloat(planeAnchor.center.y)
let z = CGFloat(planeAnchor.center.z)
planeNode.position = SCNVector3(x, y, z)
updateQueue.async {
for object in self.virtualObjectLoader.loadedObjects {
object.adjustOntoPlaneAnchor(planeAnchor, using: node)
}
}
}
在其他物体上投射阴影
试试看:
阴影平面:
func shadowPlane() -> SCNNode {
let objectShape = SCNPlane(width: 30.0, height: 30.0)
objectShape.heightSegmentCount = 1
objectShape.widthSegmentCount = 1
let objectNode = SCNNode(geometry: objectShape)
objectNode.renderingOrder = -10 // for Shadow Material Standard
objectNode.position = yourPosition
objectNode.geometry?.firstMaterial = shadowMaterialStandard()
objectNode.castsShadow = false // Important
objectNode.eulerAngles = SCNVector3(CGFloat.pi/2, 0.0, 0.0)
objectNode.name = "floor"
return objectNode
}
对于Material:
func shadowMaterialStandard() -> SCNMaterial {
let material = SCNMaterial()
material.colorBufferWriteMask = SCNColorMask(rawValue: 0) // important
material.diffuse.contents = UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
material.lightingModel = .physicallyBased // OK
material.isDoubleSided = true
return material
}
对于照明:
func directionalLight() -> SCNLight {
let light = SCNLight()
light.type = .directional
light.castsShadow = true
light.color = UIColor.white
light.shadowColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.75)
light.shadowMode = .deferred
light.shadowRadius = 2.0 // 3.25 // suggestion by Whosebug
light.shadowCascadeCount = 3 // suggestion by Whosebug
light.shadowCascadeSplittingFactor = 0.09 // suggestion by Whosebug
light.shadowBias = 0.1 // what's this?
light.shadowSampleCount = 8 // Quality of the Shadow - impacts performance when to high
light.categoryBitMask = -1 // Shine on Everything
return light
}
func ambientLight() -> SCNLight {
let light = SCNLight()
light.type = .ambient
light.color = UIColor.white
light.intensity = 250
light.categoryBitMask = -1 // Shine on Everything
return light
}