1

I'm trying to add an OpenGL context to a NSWindow, but for some reason it doesn't work. It creates and shows the NSWindow correctly when I run the app, but I can't do anything with the OpenGL context, so I presume the context hasn't been correctly added to the NSWindow.

This is my code thus far:

import Foundation
import AppKit
import GLKit

let application = NSApplication.sharedApplication()

application.setActivationPolicy(NSApplicationActivationPolicy.Regular)

let window = NSWindow(contentRect: NSMakeRect(0, 0, 640, 480), styleMask: NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask, backing: .Buffered, defer: false)

window.center()
window.title = "Programmatically Created Window"

window.makeKeyAndOrderFront(window)

class WindowDelegate: NSObject, NSWindowDelegate {
    func windowWillClose(notification: NSNotification) {
        NSApplication.sharedApplication().terminate(0)
    }
}

let windowDelegate = WindowDelegate()
window.delegate = windowDelegate

class AppDelegate: NSObject, NSApplicationDelegate {
    var window: NSWindow

    init(window: NSWindow) {
        self.window = window
    }

    func applicationDidFinishLaunching(notification: NSNotification) {
        let glContext = NSOpenGLView()

        self.window.contentView.addSubview(glContext)

//      let glAttributes: [NSOpenGLPixelFormatAttribute] = [
//          UInt32(NSOpenGLPFAAccelerated),
//          UInt32(NSOpenGLPFADoubleBuffer),
//          UInt32(NSOpenGLPFAColorSize), UInt32(48),
//          UInt32(NSOpenGLPFAAlphaSize), UInt32(16),
//          UInt32(NSOpenGLPFAMultisample),
//          UInt32(NSOpenGLPFASampleBuffers), UInt32(1),
//          UInt32(NSOpenGLPFASamples), UInt32(4),
//          UInt32(NSOpenGLPFAMinimumPolicy),
//          UInt32(0)
//      ]
//      
//      let pixelFormat = NSOpenGLPixelFormat(attributes: glAttributes)
//      let glContext = NSOpenGLContext(format: pixelFormat, shareContext: nil)

//      self.window.contentView.addSubview(glContext!.view)

//      glContext!.view = self.window.contentView as NSView
    }
}

let applicationDelegate = AppDelegate(window: window)

application.delegate = applicationDelegate
application.activateIgnoringOtherApps(true)
application.run()

glClearColor(0, 0, 0, 0)
1
  • 1
    I don't see anywhere where you've created an NSOpenGLView. Somewhere you should have an a class that sub-classes NSOpenGLView where you can do your initialization (- (id)initWithFrame:(NSRect)frameRect) and preparation (- (void) prepareOpenGL). NSOpenGLView also has an initWithFrame: pixelFormat: initializer. It's the OpenGLView that should be added as a sub-view. Commented Dec 27, 2014 at 14:54

1 Answer 1

1

Just to illustrate my comment, here's some code. This OpenGLView gets initialized by IB, so there is an awakeFromNib method, but you'll get the idea:

#import "WispView.h"
#import "AppController.h"

@implementation WispView

// *************************** Init **************************************

- (id)initWithFrame:(NSRect)frameRect
{
    self = [super initWithFrame:frameRect];

    return self;
}

// *********************** Awake From Nib *********************************

- (void)awakeFromNib;
{
    // *********** Invoke OpenGL 4.1 and GLSL 4.1
    // ********* Default is OpenGL 2.1 and GLSL 1.2

    NSOpenGLPixelFormatAttribute attributes [] =
    {
        NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
        NSOpenGLPFADoubleBuffer,    // double buffered
        NSOpenGLPFADepthSize, (NSOpenGLPixelFormatAttribute)32, // 32 bit depth buffer
        NSOpenGLPFAAccelerated,
        (NSOpenGLPixelFormatAttribute)nil
    };

    NSOpenGLPixelFormat * pf = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
    [self setPixelFormat:pf];

    tempFractalIsDisplayed = NO;
    workingFractalIsDisplayed = NO;
    gridIsDisplayed = NO;
    attractorIsDisplayed = NO;

    return;
}

// ******************** Init OpenGL Stuff Here **********************************

- (void) prepareOpenGL
{
    [[self openGLContext] makeCurrentContext];

    // *********** Log the Current OpenGL and GLSL Versions

    NSLog(@"OpenGL version = %s", glGetString(GL_VERSION));
    NSLog(@"GLSL version = %s", glGetString(GL_SHADING_LANGUAGE_VERSION));

    //********************* General OpenGL Stuff

    glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // ** Set Background Clear Color

    glEnable(GL_DEPTH_TEST); // Hide hidden surfaces
    glDepthFunc(GL_LEQUAL);
    glClearDepth(1.0);

    glEnable(GL_TEXTURE_2D);

    glFrontFace(GL_CCW);

    return;
}

// *************************** Draw Rect **********************************

- (void)drawRect:(NSRect)dirtyRect
{
    [[self openGLContext] makeCurrentContext];

    // ******************************************** Clear the Drawable

    glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    if(tempFractalIsDisplayed)
    {
        [appController->flameFractals runTheFlameShadersWithColoringData:&appDelegate->tempColoringData];
    }

    if(workingFractalIsDisplayed)
    {
        [appController->flameFractals runTheFlameShadersWithColoringData:&appDelegate->workingColoringData];
    }

    if(gridIsDisplayed)
    {
        [appController->flameFractals runTheGridShaders];
    }

    if(attractorIsDisplayed)
    {
        [appController->flameFractals runTheFlameShadersWithColoringData:&appController->lyapunov->attractorColoringData];
    }

    [[self openGLContext] flushBuffer];

    return;
}

You don't need to do all your drawing from inside the NSOpenGLClass. Other classes can use it's context to draw as well, but you do need at least some sort of drawing update code inside the drawRect method because this method is called during resizing.

In this drawRect method, the images are actually drawn in other classes. This code only gets called by the system during resizing or transition to full screen.

Sign up to request clarification or add additional context in comments.

1 Comment

Could also override + (NSOpenGLPixelFormat*) defaultPixelFormat, as this article suggests

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.