Создание представления OpenGL без Interface Builder

Итак, я пытаюсь создать представление openGL (в моем окне). Я делаю приложение Cocoa. Мне удалось создать его с помощью Interface Builder, но в образовательных целях я хочу продолжить и сделать его без него. Только по бумагам.

И вот в чем дело, я говорю вам, что борюсь с этим. Итак, что я в основном сделал-попробовал до сих пор, так это: я создал новый класс "MyOpenGLView.h/m", унаследованный от NSOpenGLView. Я не добавлял к нему приватные переменные или методы, только имя класса. Единственное, что я сделал, это переопределил initWithFrame: (добавив внутрь него self = [super initWithFrame:pixelFormat:].) Я читал об этом в Интернете, что вы должны сначала создать его с чем-то вроде этого, прежде чем вы сможете его использовать) . вот код:

- (id) initWithFrame:(NSRect)frameRect
{
 NSOpenGLPixelFormat *pixelFormat = [[NSOpenGLPixelFormat alloc]
                                    initWithAttributes:(NSOpenGLPixelFormatAttribute[])
                                    {
                                    NSOpenGLPFAWindow,
                                    NSOpenGLPFADoubleBuffer,
                                    NSOpenGLPFADepthSize, 32,
                                    nil
                                    }];
 self = [super initWithFrame:frameRect pixelFormat:pixelFormat];
 [[self openGLContext] makeCurrentContext];
}

Итак, у меня есть еще один класс с именем «MyViewController.h/m», который обрабатывает мой вид? и там у меня есть MyOpenGLView *myView. В файле .m я делаю что-то вроде этого:

myView = [[MyOpenGLView alloc] initWithFrame:CGRectMake(0,0,100.0,100.0)];
if (!myView) { NSLog(@"ERROR"); }

и, конечно, я получаю ошибку.

В моем оконном приложении нет порта openGL. Я бы предположил, что это что-то об иерархии вызываемых методов, но опять же... я не уверен. Вы можете помочь мне с этим?


person apoiat    schedule 19.12.2011    source источник


Ответы (2)


Я заставил это работать, потому что, на мой взгляд, я не реализую метод init. Затем в моем контроллере или делегате приложения у меня есть.

@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

Может сделать вызов -makeCurrentContext в вашем методе -prepareOpenGl. Все, что я написал ниже, не обязательно, но приятно для производительности. Я начал использовать CVDisplayLink для синхронизации отрисовки кадров с частотой обновления экрана, поэтому мой openGLview выглядит так:

// 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);
}
person user1139069    schedule 10.01.2012
comment
self.view = [[OpenGLViewCoreProfile alloc] initWithFrame:mainDisplayRect pixelFormat:pix]; -Разве ты не открываешь вид здесь? - person apoiat; 25.01.2012
comment
да. Однако я не написал свой собственный метод initWithFrame:pixelFormat:. Я полагаюсь на метод, унаследованный от NSOpenGLView. - person user1139069; 26.01.2012

Хотя приведенные выше ответы дают больше информации об OpenGL, причина конкретной проблемы, с которой вы столкнулись, заключается в том, что ваш метод initWithFrame должен возвращать себя.

Без этого initWithFrame всегда будет возвращать Nil. (Вы также должны вызвать супер initWithFrame и воспользоваться другим советом OpenGL).

person redfood    schedule 19.06.2012