Настройка OpenGL в Swift 3

#opengl #swift3 #xcode8 #macos-sierra

#opengl #swift3 #xcode8 #macos-sierra

Вопрос:

У меня есть почтенное приложение, которое я перенес из примера кода Apple GLEssentials в obj-c в Swift 2, и теперь я пытаюсь перейти на Swift 3. В его основе лежит NSOpenGLView, основного средства визуализации все еще нет в Swift (я знаю: мне скоро придется стиснуть зубы и перейти на Metal или что-то подобное), но все остальное есть.

В настоящее время в OSX 10.12 с Xcode 8 окно просто пустое. Мне пришлось внести некоторые предложенные компилятором изменения в основной (Swift) класс OpenGLView, чтобы он успешно компилировался и запускался в Swift 3, и я чувствую, что в этом и заключается проблема, поскольку класс рендеринга, похоже, работает нормально; я могу заставить его сообщать о FPS 60и я могу устанавливать точки останова, которые останавливают код в каждом кадре. Мой класс OpenGLView настроен так, как показано ниже, и именно здесь произошло большинство новых изменений в 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(amp;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 или приведенный выше код правильный, а проблема где-то в другом месте?

Ответ №1:

Оказывается, это был слегка поврежденный проект Xcode. Единственное, что не работало, это представление OpenGL. Возможно, просто наконечник был плохим.

Я запустил новый проект и вырезал вставил код в новые файлы и тщательно перестроил пользовательский интерфейс, и все работало просто отлично. Это научит меня не настраивать windows программно!