SceneKit结合CIFilter渲染异常:光晕效果显示层级错误
解决SceneKit中CIBloom滤镜光晕被遮挡且保留3D深度的问题
问题原因
当直接给SCNNode添加Core Image滤镜时,SceneKit会先将该节点渲染到离屏缓冲区,应用滤镜后再把结果混合到主场景。这个过程不会读取主场景的深度缓冲数据,导致滤镜生成的光晕被后方物体遮挡。而设置writesToDepthBuffer = false虽然能让光晕显示在前方,但会丢失节点本身的深度信息,旋转场景时会出现位置错乱。
解决方案:分离原节点与光晕层
通过创建两个节点分离渲染逻辑:
- 原节点:正常渲染,保留深度写入,确保3D位置关系正确
- 光晕节点:复用原节点的几何体,仅应用bloom滤镜,关闭深度写入,只显示光晕效果
修改后的代码示例
import UIKit import QuartzCore import SceneKit class GameViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // 创建场景 let scene = SCNScene() // 创建相机 let cameraNode = SCNNode() cameraNode.camera = SCNCamera() scene.rootNode.addChildNode(cameraNode) cameraNode.position = SCNVector3(x: 0, y: 0, z: 15) // 绿色立方体(后方物体) let box = SCNNode(geometry: SCNBox(width: 8.0, height: 8.0, length: 2.0, chamferRadius: 0.0)) box.geometry?.firstMaterial?.diffuse.contents = UIColor.green box.position.z = -4 scene.rootNode.addChildNode(box) // 红色立方体(原节点,保留深度) let box2 = SCNNode(geometry: SCNBox(width: 1.0, height: 1.0, length: 1.0, chamferRadius: 0.0)) box2.geometry?.firstMaterial?.diffuse.contents = UIColor.red scene.rootNode.addChildNode(box2) // 创建光晕节点 let glowBox = SCNNode(geometry: box2.geometry!) // 设置材质为透明,仅保留滤镜生成的光晕 glowBox.geometry?.firstMaterial?.diffuse.contents = UIColor.clear // 关闭深度写入,避免遮挡原节点,同时光晕可显示在其他物体前方 glowBox.geometry?.firstMaterial?.writesToDepthBuffer = false // 添加Bloom滤镜 let bloomFilter = CIFilter(name:"CIBloom")! bloomFilter.setValue(10.0, forKey: "inputIntensity") bloomFilter.setValue(100.0, forKey: "inputRadius") glowBox.filters = [bloomFilter] // 将光晕节点绑定到原节点,同步位置与旋转 box2.addChildNode(glowBox) // 配置SCNView let scnView = self.view as! SCNView scnView.scene = scene scnView.allowsCameraControl = true scnView.autoenablesDefaultLighting = true scnView.showsStatistics = true scnView.backgroundColor = UIColor.black } override var prefersStatusBarHidden: Bool { return true } override var supportedInterfaceOrientations: UIInterfaceOrientationMask { if UIDevice.current.userInterfaceIdiom == .phone { return .allButUpsideDown } else { return .all } } }
效果说明
修改后:
- 红色立方体保留完整的深度信息,旋转场景时3D位置关系完全正确
- 光晕节点由于关闭了深度写入,会渲染在所有物体前方,不会被绿色立方体遮挡
- 光晕与原节点绑定,同步移动和旋转,视觉效果一致
内容的提问来源于stack exchange,提问作者Andy3000
相关产品推荐
相关产品推荐

