在 Swift 3 中设置 OpenGL
Setting up OpenGL in Swift 3
我有一个受人尊敬的应用程序,我从 obj-c 中的 Apple 示例代码 GLEssentials 强制转换为 Swift 2,现在我正尝试移动到 Swift 3。它在它的核心有一个 NSOpenGLView,主渲染器仍然不在 Swift 中(我知道:我必须尽快硬着头皮迁移到 Metal 或类似的东西),但其他一切都在。
目前在 OSX 10.12 中,Xcode 8 window 只是空白。我不得不对主要 (Swift) OpenGLView class 进行一些编译器建议的更改,以使其在 Swift 3 中成功编译并 运行,我觉得这就是问题所在,因为渲染器 class 似乎 运行ning 很好;我可以让它报告 60 的 FPS,并且能够放置断点来停止每一帧的代码。我的 OpenGLView class 设置如下,这是大部分新 Swift 3 更改发生的地方:
class BQSOpenGLView: NSOpenGLView {
var m_renderer: OpenGLRenderer = OpenGLRenderer()
var have_setup_renderer: Bool = false
var displayLink: CVDisplayLink?
var has_setup = false
var is_fullscreen: Bool = false
var grid_size: QSGridSize = QSMakeGridSize(1, 1)
var backing_scalar_changed: Bool = false
var backing_scalar: GLfloat = 0.0
override func awakeFromNib() {
backing_scalar = GLfloat((self.window?.backingScaleFactor)!)
NotificationCenter.default.addObserver(self, selector: #selector(BQSOpenGLView.willEnterFullscreen(_:)), name: NSNotification.Name.NSWindowWillEnterFullScreen, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(BQSOpenGLView.willExitFullscreen(_:)), name: NSNotification.Name.NSWindowWillExitFullScreen, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(BQSOpenGLView.backingScaleChange(_:)), name: NSNotification.Name.NSWindowDidChangeBackingProperties, object: nil)
let attributes : [NSOpenGLPixelFormatAttribute] = [
NSOpenGLPixelFormatAttribute(NSOpenGLPFADoubleBuffer),
NSOpenGLPixelFormatAttribute(NSOpenGLPFADepthSize),
NSOpenGLPixelFormatAttribute(24),
NSOpenGLPixelFormatAttribute(NSOpenGLPFASampleBuffers),
NSOpenGLPixelFormatAttribute(1),
NSOpenGLPixelFormatAttribute(NSOpenGLPFASamples),
NSOpenGLPixelFormatAttribute(2),
NSOpenGLPixelFormatAttribute(NSOpenGLPFAOpenGLProfile),
NSOpenGLPixelFormatAttribute(NSOpenGLProfileVersion3_2Core),
NSOpenGLPixelFormatAttribute(0)
]
self.pixelFormat = NSOpenGLPixelFormat(attributes: attributes)
self.wantsBestResolutionOpenGLSurface = true
let context:NSOpenGLContext = NSOpenGLContext.init(format: self.pixelFormat!, share: nil)!
CGLEnable(context.cglContextObj!, kCGLCECrashOnRemovedFunctions)
self.openGLContext = context
}
override func prepareOpenGL() {
super.prepareOpenGL()
// The callback function is called everytime CVDisplayLink says its time to get a new frame.
func displayLinkOutputCallback(_ displayLink: CVDisplayLink, _ inNow: UnsafePointer<CVTimeStamp>, _ inOutputTime: UnsafePointer<CVTimeStamp>, _ flagsIn: CVOptionFlags, _ flagsOut: UnsafeMutablePointer<CVOptionFlags>, _ displayLinkContext: UnsafeMutableRawPointer?) -> CVReturn {
unsafeBitCast(displayLinkContext, to: BQSOpenGLView.self).renderFrame()
return kCVReturnSuccess
}
self.wantsLayer = true
self.wantsBestResolutionOpenGLSurface = true
CVDisplayLinkCreateWithActiveCGDisplays(&displayLink)
let success = CVDisplayLinkSetOutputCallback(displayLink!, displayLinkOutputCallback, Unmanaged.passUnretained(self).toOpaque())
if success != kCVReturnSuccess {
Swift.print ("No opengl")
}
CVDisplayLinkStart(displayLink!)
has_setup = true
NotificationCenter.default.post(name: Notification.Name(rawValue: kOPENGL_SETUP_NOTE), object: nil)
self.backingScaleChange(nil)
}
//..
}
渲染方法是:
func renderFrame() {
self.openGLContext?.makeCurrentContext()
CGLLockContext((self.openGLContext?.cglContextObj)!)
if !have_setup_renderer { //init only when locked all the context
self.backingScaleChange(nil)
m_renderer = OpenGLRenderer.init(defaultFBO: 0, screenSize: (self.window?.screen?.frame.size)!, backingScalar: self.backing_scalar)
have_setup_renderer = true
}
m_renderer.render()
CGLFlushDrawable((self.openGLContext?.cglContextObj)!)
CGLUnlockContext((self.openGLContext?.cglContextObj)!)
}
是否有新的 Swift 3 设置 OpenGL 的方法,或者上面的代码是否正确但问题出在其他地方?
原来是一个微妙的腐败 Xcode 项目。唯一不起作用的是 OpenGL 视图。可能只是笔尖不好
我开始了一个新项目,将代码剪切并粘贴到新文件中,然后费力地重建了 UI,一切正常。这将教会我不要以编程方式设置 windows!
我有一个受人尊敬的应用程序,我从 obj-c 中的 Apple 示例代码 GLEssentials 强制转换为 Swift 2,现在我正尝试移动到 Swift 3。它在它的核心有一个 NSOpenGLView,主渲染器仍然不在 Swift 中(我知道:我必须尽快硬着头皮迁移到 Metal 或类似的东西),但其他一切都在。
目前在 OSX 10.12 中,Xcode 8 window 只是空白。我不得不对主要 (Swift) OpenGLView class 进行一些编译器建议的更改,以使其在 Swift 3 中成功编译并 运行,我觉得这就是问题所在,因为渲染器 class 似乎 运行ning 很好;我可以让它报告 60 的 FPS,并且能够放置断点来停止每一帧的代码。我的 OpenGLView class 设置如下,这是大部分新 Swift 3 更改发生的地方:
class BQSOpenGLView: NSOpenGLView {
var m_renderer: OpenGLRenderer = OpenGLRenderer()
var have_setup_renderer: Bool = false
var displayLink: CVDisplayLink?
var has_setup = false
var is_fullscreen: Bool = false
var grid_size: QSGridSize = QSMakeGridSize(1, 1)
var backing_scalar_changed: Bool = false
var backing_scalar: GLfloat = 0.0
override func awakeFromNib() {
backing_scalar = GLfloat((self.window?.backingScaleFactor)!)
NotificationCenter.default.addObserver(self, selector: #selector(BQSOpenGLView.willEnterFullscreen(_:)), name: NSNotification.Name.NSWindowWillEnterFullScreen, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(BQSOpenGLView.willExitFullscreen(_:)), name: NSNotification.Name.NSWindowWillExitFullScreen, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(BQSOpenGLView.backingScaleChange(_:)), name: NSNotification.Name.NSWindowDidChangeBackingProperties, object: nil)
let attributes : [NSOpenGLPixelFormatAttribute] = [
NSOpenGLPixelFormatAttribute(NSOpenGLPFADoubleBuffer),
NSOpenGLPixelFormatAttribute(NSOpenGLPFADepthSize),
NSOpenGLPixelFormatAttribute(24),
NSOpenGLPixelFormatAttribute(NSOpenGLPFASampleBuffers),
NSOpenGLPixelFormatAttribute(1),
NSOpenGLPixelFormatAttribute(NSOpenGLPFASamples),
NSOpenGLPixelFormatAttribute(2),
NSOpenGLPixelFormatAttribute(NSOpenGLPFAOpenGLProfile),
NSOpenGLPixelFormatAttribute(NSOpenGLProfileVersion3_2Core),
NSOpenGLPixelFormatAttribute(0)
]
self.pixelFormat = NSOpenGLPixelFormat(attributes: attributes)
self.wantsBestResolutionOpenGLSurface = true
let context:NSOpenGLContext = NSOpenGLContext.init(format: self.pixelFormat!, share: nil)!
CGLEnable(context.cglContextObj!, kCGLCECrashOnRemovedFunctions)
self.openGLContext = context
}
override func prepareOpenGL() {
super.prepareOpenGL()
// The callback function is called everytime CVDisplayLink says its time to get a new frame.
func displayLinkOutputCallback(_ displayLink: CVDisplayLink, _ inNow: UnsafePointer<CVTimeStamp>, _ inOutputTime: UnsafePointer<CVTimeStamp>, _ flagsIn: CVOptionFlags, _ flagsOut: UnsafeMutablePointer<CVOptionFlags>, _ displayLinkContext: UnsafeMutableRawPointer?) -> CVReturn {
unsafeBitCast(displayLinkContext, to: BQSOpenGLView.self).renderFrame()
return kCVReturnSuccess
}
self.wantsLayer = true
self.wantsBestResolutionOpenGLSurface = true
CVDisplayLinkCreateWithActiveCGDisplays(&displayLink)
let success = CVDisplayLinkSetOutputCallback(displayLink!, displayLinkOutputCallback, Unmanaged.passUnretained(self).toOpaque())
if success != kCVReturnSuccess {
Swift.print ("No opengl")
}
CVDisplayLinkStart(displayLink!)
has_setup = true
NotificationCenter.default.post(name: Notification.Name(rawValue: kOPENGL_SETUP_NOTE), object: nil)
self.backingScaleChange(nil)
}
//..
}
渲染方法是:
func renderFrame() {
self.openGLContext?.makeCurrentContext()
CGLLockContext((self.openGLContext?.cglContextObj)!)
if !have_setup_renderer { //init only when locked all the context
self.backingScaleChange(nil)
m_renderer = OpenGLRenderer.init(defaultFBO: 0, screenSize: (self.window?.screen?.frame.size)!, backingScalar: self.backing_scalar)
have_setup_renderer = true
}
m_renderer.render()
CGLFlushDrawable((self.openGLContext?.cglContextObj)!)
CGLUnlockContext((self.openGLContext?.cglContextObj)!)
}
是否有新的 Swift 3 设置 OpenGL 的方法,或者上面的代码是否正确但问题出在其他地方?
原来是一个微妙的腐败 Xcode 项目。唯一不起作用的是 OpenGL 视图。可能只是笔尖不好
我开始了一个新项目,将代码剪切并粘贴到新文件中,然后费力地重建了 UI,一切正常。这将教会我不要以编程方式设置 windows!