ARKit –sceneView 以 120 fps 渲染其内容(但我需要 30 fps)

ARG*_*Geo 6 augmented-reality scenekit swift apple-vision arkit

我正在开发 ARKit 应用程序和Vision/AVKit框架。我的应用程序识别用于控制视频的手势(“胜利”、“Okey”、“拳头”手势)。所以我用MLModel我的手势分类。

应用程序工作正常,但视图的内容以120 fps呈现。我不需要这样的帧率。这对我的应用程序来说太多了,对 CPU 来说是一个沉重的负担。我尝试使用 SceneKit 的实例属性将帧速率降低到30 fps

var preferredFramesPerSecond: Int { get set }
Run Code Online (Sandbox Code Playgroud)

但我的帧速率仍然相同——120 fps。

在此处输入图片说明

这是我如何做到的:

import UIKit
import AVKit
import SceneKit
import ARKit
import Vision

class ViewController: UIViewController, ARSCNViewDelegate {

    @IBOutlet var sceneView: ARSCNView! 
    var avPlayerView = AVPlayerViewController()
    private let player = AVQueuePlayer()
    let clips = ["AA", "BB", "CC"]
    private var token: NSKeyValueObservation?
    var number: Int = 0
    var once: Bool = true    
    let dispatchQueueML = DispatchQueue(label: "net.aaa.iii") 
    var visionRequests = [VNRequest]()

    override func viewDidLoad() {
        super.viewDidLoad()
        sceneView.delegate = self
        sceneView.showsStatistics = true
        sceneView.preferredFramesPerSecond = 30     // HERE IT GOES
        sceneView.rendersContinuously = true
    
        let scene = SCNScene()
        sceneView.scene = scene
        sceneView.scene.background.contents = UIColor.black.withAlphaComponent(0)
    
        guard let selectedModel = try? VNCoreMLModel(for: handsModel().model) else {
            fatalError("Couldn't load a model.")
        }
    
        let classificationRequest = VNCoreMLRequest(model: selectedModel, 
                                        completionHandler: classificationCompleteHandler)
        classificationRequest.imageCropAndScaleOption = VNImageCropAndScaleOption.centerCrop
        visionRequests = [classificationRequest]       
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        self.addAllVideosToPlayer()
        present(avPlayerView, animated: true,
                            completion: { self.player.play() })
    
        let configuration = ARWorldTrackingConfiguration()
        configuration.isAutoFocusEnabled = false
        sceneView.session.run(configuration)
    }

    func addAllVideosToPlayer() {
        avPlayerView.player = player
        // .........................
    }
    func toggleNextVideo() {
        // ..............
    }
    func togglePreviousVideo() {
        // ..............
    }

    // ..............................
    // ..............................

    DispatchQueue.main.async {
        if (topPredictionScore != nil && topPredictionScore! > 0.01) {  
            if (topPredictionName == "FistGesture") && (self.once == false) {
                self.once = true
            }
            if (topPredictionName == "OkeyGesture") && (self.once == true) {
                self.toggleNextVideo()
                self.once = false
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是Apple对此的说法

SceneKit 根据显示视图的屏幕的功能选择尽可能接近您首选帧速率的实际帧速率。实际帧率通常是屏幕最大刷新率的一个因素,以提供一致的帧率。

例如,如果屏幕的最大刷新率是60fps,那也是视图设置的最高帧率作为实际帧率。但是,如果你问一个较低的帧速率,SceneKit可以选择302015或其他一些因素是实际的帧速率。出于这个原因,您希望选择您的应用程序可以始终保持的帧速率。默认值为60fps。

如何将视图的帧速率降低到 30 fps

ARG*_*Geo 4

场景套件 + SwiftUI

\n

使用 SwiftUI 界面(iOS 14+ 和 macOS 11+)时,您可以选择运行 SwiftUI 应用程序的 SceneKit 视图的简化配置。它允许我们更改帧速率。

\n
SceneView(scene: SCNScene? = nil, pointOfView: SCNNode? = nil,\n                         options: SceneView.Options = [],\n        preferredFramesPerSecond: Int = 30,\n                antialiasingMode: SCNAntialiasingMode = .multisampling4X,\n                        delegate: SCNSceneRendererDelegate? = nil,\n                       technique: SCNTechnique? = nil)\n
Run Code Online (Sandbox Code Playgroud)\n

在此输入图像描述

\n


\n

SpriteKit + UIKit

\n

使用 UIKit 故事板时,SceneKit 不允许我们更改帧速率 \xe2\x80\x93 它具有固定的60 fps120 fps。所以我们可以使用SpriteKit框架 \xe2\x80\x93 它允许我们设置30 fps

\n

在此输入图像描述

\n

这是代码:

\n
import SpriteKit\n\nclass ViewController: UIViewController, ARSKViewDelegate {\n\n    @IBOutlet weak var skSceneView: ARSKView!\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n\n        skSceneView.delegate = self\n        skSceneView.preferredFramesPerSecond = 30 \n    \n        let scene = SKScene()\n        skSceneView.presentScene(scene)\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

  • 我正在使用 SceneKit,当我设置首选帧速率时,它适用于我的情况:“[self.sceneView setPreferredFramesPerSecond:30];”也许您有多个 Metal 配置,因此每种配置的不同帧速率会在 Xcode 中堆积起来仪表,试试这个,将你的 Metal 东西设置为 30,你的场景也设置为 30,我的猜测是仅使用 SceneKit 时为 30,一旦我们添加另一个金属配置/实例,它就会变为 60。我还建议使用 ScenKit 调试视图,它们会在设备中显示它们正在运行的真实 FPS。 (2认同)