Thanks for your help. Now the app doesn't crash anymore, but the colours of textures shown in SKSpriteNode are a little bit off.
To reproduce this, add the below image as a new image resource named "blue" in the Xcode project. It contains a single color RGB = (71, 147, 191).
When shown in ARView, it is rendered as RGB = (93, 201, 227), which is visibly different than the original image.
When shown in SKView, it is rendered as RGB = (28, 149, 195), which is still slightly different than the original image, but close enough that I didn't notice it before doing this measurement.
Why is the colour so different in ARView? (Optional question: why is it also slightly different in SKView?)
Also, I'm not sure what I should do in order to not create the texture every frame, since its size is dependent on the size of the postProcess context. Should I store the texture in an instance variable and generate it again when the size of the old one doesn't match the size of context.targetColorTexture?
I created FB22541137.
import Cocoa
import SpriteKit
import RealityKit
class ViewController: NSViewController {
var device: MTLDevice!
var renderer: SKRenderer!
override func loadView() {
let arView = ARView(frame: NSScreen.main!.frame)
view = arView
// let skView = SKView(frame: NSScreen.main!.frame)
// skView.presentScene(createScene())
// view = skView
arView.renderCallbacks.prepareWithDevice = { [weak self] device in
guard let self = self else { return }
self.device = device
renderer = SKRenderer(device: device)
renderer.scene = createScene()
}
arView.renderCallbacks.postProcess = { [weak self] context in
guard let self = self else { return }
let encoder = context.commandBuffer.makeBlitCommandEncoder()
encoder?.copy(from: context.sourceColorTexture, to: context.targetColorTexture)
encoder?.endEncoding()
renderer.update(atTime: context.time)
let depthStencilDescriptor = MTLTextureDescriptor()
depthStencilDescriptor.pixelFormat = .depth32Float_stencil8
depthStencilDescriptor.width = context.targetColorTexture.width
depthStencilDescriptor.height = context.targetColorTexture.height
depthStencilDescriptor.usage = .renderTarget
depthStencilDescriptor.storageMode = .private
let texture = device!.makeTexture(descriptor: depthStencilDescriptor)
let renderPassDescriptor = MTLRenderPassDescriptor()
renderPassDescriptor.colorAttachments[0].loadAction = .load
renderPassDescriptor.colorAttachments[0].storeAction = .store
renderPassDescriptor.colorAttachments[0].texture = context.targetColorTexture
renderPassDescriptor.depthAttachment.texture = texture
renderPassDescriptor.depthAttachment.loadAction = .clear
renderPassDescriptor.depthAttachment.storeAction = .dontCare
renderPassDescriptor.depthAttachment.clearDepth = 1.0
renderPassDescriptor.stencilAttachment.texture = texture
renderPassDescriptor.stencilAttachment.loadAction = .clear
renderPassDescriptor.stencilAttachment.storeAction = .dontCare
renderPassDescriptor.stencilAttachment.clearStencil = 0
renderer.render(withViewport: CGRect(x: 0, y: 0, width: context.targetColorTexture.width, height: context.targetColorTexture.height), commandBuffer: context.commandBuffer, renderPassDescriptor: renderPassDescriptor)
}
}
private func createScene() -> SKScene {
let scene = SKScene(size: CGSize(width: 100, height: 100))
scene.addChild(SKSpriteNode(texture: SKTexture(imageNamed: "blue"), size: CGSize(width: 100, height: 100)))
return scene
}
}