You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 02:35:40