'SceneKit Cocoa snapshot failed assertion
I am working on a Swift/Cocoa/Xcode application.
This application contains a SceneKit View. The rendering API is set to Default (I think this is Metal).
If I run a snapshot()
on this SceneKit view object, I get this error message. What I want to do is to capture an UIImage of the scene, viewed from camera
Texture PixelFormat MTLPixelFormatBGRA8Unorm does not match Resolve PixelFormat MTLPixelFormatRGBA8Unorm
If I set the rendering API to OpenGL
, I have no error, everything works.
I have tried the same thing on an iOS app, it works on both cases (Metal or OpenGL).
I do not understand why I get this error and what should I do to avoid it.
Here is sample code:
import SceneKit
import Cocoa
class ViewController: NSViewController {
@IBOutlet weak var vue_scene: SCNView!
@IBOutlet weak var img_snapshot: NSImageView!
let camera_node = SCNNode()
var box_node:SCNNode = SCNNode()
override func viewDidLoad() {
super.viewDidLoad()
let scene = SCNScene()
vue_scene.scene = scene
vue_scene.backgroundColor = NSColor.clear
vue_scene.showsStatistics = false
vue_scene.allowsCameraControl = false
vue_scene.autoenablesDefaultLighting = true
camera_node.camera = SCNCamera()
camera_node.camera?.zNear = 0.01
camera_node.camera?.zFar = 1000000.0
vue_scene.pointOfView = camera_node
vue_scene.scene!.rootNode.addChildNode(camera_node)
let box = SCNBox(width: 10.0,
height: 10.0,
length: 10.0,
chamferRadius: 0.0)
box.firstMaterial?.diffuse.contents = NSColor.red
box.firstMaterial?.isDoubleSided = true
box_node = SCNNode(geometry:box)
box_node.position = SCNVector3Make(0,0,0)
box_node.opacity = 1.0
vue_scene.scene!.rootNode.addChildNode(box_node)
camera_node.position = SCNVector3Make(0.0,
0.0,
70.0)
}
@IBAction func on_btn(_ sender: Any) {
// signal SIGABRT here:
// /Library/Caches/com.apple.xbs/Sources/Metal/Metal-56.6.1/ToolsLayers/Debug/MTLDebugCommandBuffer.mm:215: failed assertion `Texture PixelFormat MTLPixelFormatBGRA8Unorm does not match Resolve PixelFormat MTLPixelFormatRGBA8Unorm'
let image = vue_scene.snapshot()
img_snapshot.image = image;
}
}
Solution 1:[1]
It works on Metal.
In macOS use Tab View
(for example) for accommodation of SceneView
and NSImageView
.
I also tested it in Xcode 13.3 on macOS 12.3 Monterey.
import SceneKit
import Cocoa
class ViewController: NSViewController {
@IBOutlet var sceneView: SCNView!
@IBOutlet var imageView: NSImageView!
override func viewDidLoad() {
super.viewDidLoad()
sceneView.scene = SCNScene()
sceneView.pointOfView?.position.z = 20
sceneView.allowsCameraControl = true
sceneView.showsStatistics = true
sceneView.backgroundColor = NSColor.black
sceneView.autoenablesDefaultLighting = true
let box = SCNBox(width: 1.0, height: 1.0,
length: 1.0, chamferRadius: 0.0)
box.firstMaterial?.diffuse.contents = NSColor.systemTeal
let boxNode = SCNNode(geometry: box)
boxNode.position = SCNVector3(0,0,-10)
sceneView.scene!.rootNode.addChildNode(boxNode)
}
@IBAction func createSnapshot(_ sender: NSButton) {
let image = sceneView.snapshot()
imageView.image = image
}
}
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 |