我将Vuforia SDK图像目标跟踪特性成功地整合到了iOS项目中,通过将SDK提供的OpenGL上下文(EAGLContext
)与SceneKit的SCNRenderer
实例相结合。这使我能够利用SceneKit的3D API的简单性,同时又从Vuforia的高精度图像检测中受益。现在,我想通过使用Metal来替换OpenGL来做同样的事情。
一些背景故事:
我能够使用OpenGL在Vuforia绘制的实时视频纹理上方绘制SceneKit对象而没有遇到主要问题。
以下是我使用的简化设置与OpenGL:
func configureRenderer(for context: EAGLContext) {
self.renderer = SCNRenderer(context: context, options: nil)
self.scene = SCNScene()
renderer.scene = scene
// other scenekit setup
}
func render() {
// manipulate scenekit nodes
renderer.render(atTime: CFAbsoluteTimeGetCurrent())
}
苹果在iOS 12上弃用了OpenGL
自从苹果宣布在iOS 12上弃用OpenGL,我认为将该项目迁移到使用Metal
而不是OpenGL
是一个好主意。
理论上应该很简单,因为Vuforia支持开箱即用的Metal。但是,在尝试集成它时,我遇到了困难。
问题
视图似乎只会渲染SceneKit渲染器的结果或由Vuforia编码的纹理,但两者永远不会同时出现。这取决于哪个先编码。我该怎么做才能混合两个结果?
以下是问题设置的要点:
func configureRenderer(for device: MTLDevice) {
let renderer = SCNRenderer(device: device, options: nil)
self.scene = SCNScene()
renderer.scene = scene
// other scenekit setup
}
func render(viewport: CGRect, commandBuffer: MTLCommandBuffer, drawable: CAMetalDrawable) {
// manipulate scenekit nodes
let renderPassDescriptor = MTLRenderPassDescriptor()
renderPassDescriptor.colorAttachments[0].texture = drawable.texture
renderPassDescriptor.colorAttachments[0].loadAction = .load
renderPassDescriptor.colorAttachments[0].storeAction = .store
renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColor(red: 0.0, green: 0, blue: 0, alpha: 0)
renderer!.render(withViewport: viewport, commandBuffer: commandBuffer, passDescriptor: renderPassDescriptor)
}
我尝试在 encoder.endEncoding
之后或在 commandBuffer.renderCommandEncoderWithDescriptor
之前调用 render
方法:
metalDevice = MTLCreateSystemDefaultDevice();
metalCommandQueue = [metalDevice newCommandQueue];
id<MTLCommandBuffer>commandBuffer = [metalCommandQueue commandBuffer];
//// -----> call the `render(viewport:commandBuffer:drawable) here <------- \\\\
id<MTLRenderCommandEncoder> encoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];
// calls to encoder to render textures from Vuforia
[encoder endEncoding];
//// -----> or here <------- \\\\
[commandBuffer presentDrawable:drawable];
[commandBuffer commit];
无论哪种情况,我只能看到
SCNRenderer
的结果或者encoder
的结果,但是从来没有在同一个视图中同时显示两者的结果。对我来说,好像上面的编码过程和
SCNRenderer.render
会相互覆盖各自的缓冲区。我错过了什么吗?