Creating an OpenGL View without Interface Builder

前端 未结 2 899
眼角桃花
眼角桃花 2020-12-28 23:57

So im trying to create an openGL view (in my window). Im making a Cocoa app. Ive managed to create one through Interface Builder, but for educational purposes i want to go o

相关标签:
2条回答
  • 2020-12-29 00:35

    While the answers above give more information about OpenGL the reason for the specific issue you are having is that your initWithFrame method needs to return self.

    Without that initWithFrame will always return Nil. (You should also call super's initWithFrame and take the other OpenGL advice).

    0 讨论(0)
  • 2020-12-29 00:40

    They way I have gotten this to work is I don't implement an init method in my view. Then in my controller or app delegate I have.

    @implementation AppDelegate
    
    @synthesize window = _window;
    @synthesize view = _view;
    
    - (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
        NSRect mainDisplayRect = [[NSScreen mainScreen] frame]; // I'm going to make a full screen view.
    
        NSOpenGLPixelFormatAttribute attr[] = {
            NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core, // Needed if using opengl 3.2 you can comment this line out to use the old version.
            NSOpenGLPFAColorSize,     24,
            NSOpenGLPFAAlphaSize,     8,
            NSOpenGLPFAAccelerated,
            NSOpenGLPFADoubleBuffer,
            0
        };
    
        NSOpenGLPixelFormat *pix = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr];
        self.view = [[OpenGLViewCoreProfile alloc] initWithFrame:mainDisplayRect pixelFormat:pix];
    
        // Below shows how to make the view fullscreen. But you could just add to the contact view of any window.
        self.window = [[NSWindow alloc] initWithContentRect:mainDisplayRect
                                                  styleMask:NSBorderlessWindowMask 
                                                    backing:NSBackingStoreBuffered 
                                                      defer:YES];
    
        self.window.opaque = YES;
        self.window.hidesOnDeactivate = YES;
        self.window.level = NSMainMenuWindowLevel + 1; // Show window above main menu.
        self.window.contentView = self.view;
        [self.window makeKeyAndOrderFront:self]; // Display window.
    }
    
    @end
    

    Can can make call -makeCurrentContext in your -prepareOpenGl method. All that I have written below is not necessary but nice for performance reasons. I have started using the CVDisplayLink to sync frame drawing with the screen refresh rate so my openGLview looks like

    // This is the callback function for the display link.
    static CVReturn OpenGLViewCoreProfileCallBack(CVDisplayLinkRef displayLink,
                                                  const CVTimeStamp* now, 
                                                  const CVTimeStamp* outputTime, 
                                                  CVOptionFlags flagsIn, 
                              CVOptionFlags *flagsOut, 
                                                  void *displayLinkContext) {
        @autoreleasepool {
            OpenGLViewCoreProfile *view = (__bridge OpenGLViewCoreProfile*)displayLinkContext;
            [view.openGLContext makeCurrentContext];
            CGLLockContext(view.openGLContext.CGLContextObj); // This is needed because this isn't running on the main thread.
            [view drawRect:view.bounds]; // Draw the scene. This doesn't need to be in the drawRect method.
            CGLUnlockContext(view.openGLContext.CGLContextObj);
            CGLFlushDrawable(view.openGLContext.CGLContextObj); // This does glFlush() for you.
    
            return kCVReturnSuccess;
        }
    }
    
    - (void)reshape {
        [super reshape];
        CGLLockContext(self.openGLContext.CGLContextObj);
    
        ... // standard opengl reshape stuff goes here.
    
        CGLUnlockContext(self.openGLContext.CGLContextObj);
    }
    
    - (void)prepareOpenGL {
        [super prepareOpenGL];
    
        [self.openGLContext makeCurrentContext];
        GLint swapInt = 1;
        [self.openGLContext setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
    
        CGLLockContext(self.openGLContext.CGLContextObj);
    
        ... // all opengl prep goes here
    
        CGLUnlockContext(self.openGLContext.CGLContextObj);
    
        // Below creates the display link and tell it what function to call when it needs to draw a frame.
        CVDisplayLinkCreateWithActiveCGDisplays(&_displayLink);
        CVDisplayLinkSetOutputCallback(self.displayLink, &OpenGLViewCoreProfileCallBack, (__bridge void *)self);
        CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(self.displayLink, 
                                                          self.openGLContext.CGLContextObj, 
                                                          self.pixelFormat.CGLPixelFormatObj);
        CVDisplayLinkStart(self.displayLink);
    }
    
    0 讨论(0)
提交回复
热议问题