gpt4 book ai didi

ios - SceneKit - 在不使用单独的 SCNRenderer 的情况下从 SCNView 获取渲染场景作为 MTLTexture

转载 作者:可可西里 更新时间:2023-11-01 03:56:36 26 4
gpt4 key购买 nike

我的 SCNView 使用 Metal 作为渲染 API,我想知道是否有一种方法可以将渲染场景抓取为 MTLTexture 而无需使用单独的SCN渲染器?当我尝试通过 SCNView 显示场景并通过 SCNRenderer 将屏幕外的场景重新渲染到 MTLTexture 时,性能下降(我试图抓取每一帧的输出)。

SCNView 让我可以访问它使用的 MTLDeviceMTLRenderCommandEncoderMTLCommandQueue,但不能为了获得MTLTexture(通过renderPassDescriptor.colorAttachments[0].texture)我需要底层的MTLRenderPassDescriptor

我尝试的一些替代方法是尝试使用 SCNView.snapshot() 获取 UIImage 并转换它,但性能更差。

最佳答案

针对 Swift 4 更新:

Swift 4 不支持 dispatch_once(),并且在替换函数中添加了@objc。这是更新的 swizzle 设置。这已经过测试,对我来说效果很好。

extension CAMetalLayer {

// Interface so user can grab this drawable at any time
private struct nextDrawableExtPropertyData {
static var _currentSceneDrawable : CAMetalDrawable? = nil
}
var currentSceneDrawable : CAMetalDrawable? {
get {
return nextDrawableExtPropertyData._currentSceneDrawable
}
}

// The rest of this is just swizzling
private static let doJustOnce : Any? = {
print ("***** Doing the doJustOnce *****")
CAMetalLayer.setupSwizzling()

return nil
}()

public static func enableNextDrawableSwizzle() {
_ = CAMetalLayer.doJustOnce
}

public static func setupSwizzling() {
print ("***** Doing the setupSwizzling *****")

let copiedOriginalSelector = #selector(CAMetalLayer.originalNextDrawable)
let originalSelector = #selector(CAMetalLayer.nextDrawable)
let swizzledSelector = #selector(CAMetalLayer.newNextDrawable)

let copiedOriginalMethod = class_getInstanceMethod(self, copiedOriginalSelector)
let originalMethod = class_getInstanceMethod(self, originalSelector)
let swizzledMethod = class_getInstanceMethod(self, swizzledSelector)

let oldImp = method_getImplementation(originalMethod!)
method_setImplementation(copiedOriginalMethod!, oldImp)

let newImp = method_getImplementation(swizzledMethod!)
method_setImplementation(originalMethod!, newImp)

}


@objc func newNextDrawable() -> CAMetalDrawable? {
// After swizzling, originalNextDrawable() actually calls the real nextDrawable()
let drawable = originalNextDrawable()

// Save the drawable
nextDrawableExtPropertyData._currentSceneDrawable = drawable

return drawable
}

@objc func originalNextDrawable() -> CAMetalDrawable? {
// This is just a placeholder. Implementation will be replaced with nextDrawable.
// ***** This will never be called *****
return nil
}
}

在你的 AppDelegate 中:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.

// Swizzle
CAMetalLayer.enableNextDrawableSwizzle()

return true
}

已更新以将 currentSceneDrawable 属性添加到 CAMetalLayer,因此您只需使用 layer.currentSceneDrawable 即可访问它,而不是让扩展程序将其存储在外部。

关于ios - SceneKit - 在不使用单独的 SCNRenderer 的情况下从 SCNView 获取渲染场景作为 MTLTexture,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40296399/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com