'How to achieve realistic Depth of Field effect in SceneKit?

I'm trying to render a frame, with realistic depth of field effect. I've already tried the depth of field properties in the camera node, but it doesn't produce usable results.

Is there a switch to max-out rendering quality of the depth of field effect? Performance is not a factor, I just need to render a frame, and user can wait for it.



Solution 1:[1]

SceneKit isn't able to do (out of the box) heavy, high quality post processing or still image rendering computation of this type. Theoretically you could probably build a setup that uses its rendering approaches to do both. But it's not a high quality renderer. If the user can wait, and you really want to focus on quality of imagery, Unreal Engine has the capacity to do this sort of thing, built in, and far higher quality post processing, effects, lights, materials, particles and rendering.

Solution 2:[2]

Realistic Depth of Field effect in SceneKit

In SceneKit you can easily accomplish cool-looking shallow/deep depth of field (DoF). And it's not extremely intense for processing. .focusDistance and .fStop parameters are crucial for applying DoF:

cameraNode.camera?.wantsDepthOfField = true
cameraNode.camera?.focusDistance = 5
cameraNode.camera?.fStop = 0.01
cameraNode.camera?.focalLength = 24

enter image description here


Use the following code for testing (it's macOS version):

import SceneKit
import Cocoa

class GameViewController: NSViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        let scene = SCNScene()
        
        let cameraNode = SCNNode()
        cameraNode.camera = SCNCamera()
        cameraNode.camera?.wantsDepthOfField = true
        cameraNode.camera?.focusDistance = 5
        cameraNode.camera?.fStop = 0.01
        cameraNode.camera?.focalLength = 24
        scene.rootNode.addChildNode(cameraNode)
        cameraNode.position = SCNVector3(x: 0, y: 0, z: 15)
        
        let lightNode = SCNNode()
        lightNode.light = SCNLight()
        lightNode.light!.type = .omni
        lightNode.position = SCNVector3(x: 0, y: 10, z: 10)
        scene.rootNode.addChildNode(lightNode)
        
        let ambientLightNode = SCNNode()
        ambientLightNode.light = SCNLight()
        ambientLightNode.light!.type = .ambient
        ambientLightNode.light!.color = NSColor.darkGray
        scene.rootNode.addChildNode(ambientLightNode)
        
        let cylinderNode01 = SCNNode()
        cylinderNode01.geometry = SCNCylinder(radius: 2, height: 10)
        cylinderNode01.position = SCNVector3(0, 0, 0)
        cylinderNode01.geometry?.materials.first?.diffuse.contents = NSImage(named: NSImage.Name("checker01.png"))
        scene.rootNode.addChildNode(cylinderNode01)
        
        let cylinderNode02 = SCNNode()
        cylinderNode02.geometry = SCNCylinder(radius: 2, height: 10)
        cylinderNode02.position = SCNVector3(5, 0, 5)
        cylinderNode02.geometry?.materials.first?.diffuse.contents = NSImage(named: NSImage.Name("checker02.jpg"))
        scene.rootNode.addChildNode(cylinderNode02)
        
        let cylinderNode03 = SCNNode()
        cylinderNode03.geometry = SCNCylinder(radius: 2, height: 10)
        cylinderNode03.position = SCNVector3(10, 0, 10)
        cylinderNode03.geometry?.materials.first?.diffuse.contents = NSImage(named: NSImage.Name("checker01.png"))
        scene.rootNode.addChildNode(cylinderNode03)
        
        let cylinderNode04 = SCNNode()
        cylinderNode04.geometry = SCNCylinder(radius: 2, height: 10)
        cylinderNode04.position = SCNVector3(-5, 0, -5)
        cylinderNode04.geometry?.materials.first?.diffuse.contents = NSImage(named: NSImage.Name("checker02.jpg"))
        scene.rootNode.addChildNode(cylinderNode04)
        
        let cylinderNode05 = SCNNode()
        cylinderNode05.geometry = SCNCylinder(radius: 2, height: 10)
        cylinderNode05.position = SCNVector3(-10, 0, -10)
        cylinderNode05.geometry?.materials.first?.diffuse.contents = NSImage(named: NSImage.Name("checker01.png"))
        scene.rootNode.addChildNode(cylinderNode05)
       
        let scnView = self.view as! SCNView
        scnView.scene = scene
        scnView.allowsCameraControl = true
        scnView.backgroundColor = NSColor.black
    }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Confused
Solution 2