使用OpenGL在mac osx cocoa应用程序中设置连续渲染

时间:2012-03-29 22:46:00

标签: xcode cocoa opengl

我开始研究3D粒子系统编辑器和evolver。我曾经用OpenGL做过类似的事情,但这次我正在制作一个mac os x cocoa应用程序。关于设置OpenGL时遇到的一些代码我只有几个问题。

1)为什么我在网上看到很多人使用...

[self setNeedsDisplay:YES];

这是获取OpenGL渲染的正确方法吗,我现在明白它会导致drawRect被调用,但这是正确的方法吗?

2)drawRect是否应该覆盖我的渲染帧方法的正确方法?

下面是我继续在网上遇到的代码:

-(void) prepareOpenGL {
    [[self window] makeFirstResponder:self];
    glClearColor(1.0f, 1.0f, 0.0f, 10.f);

    NSTimer *timer = [NSTimer timerWithTimeInterval:1.0/60.0 target:self selector:@selector(idle:) userInfo:nil repeats:YES];
   [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
}

-(void)idle:(NSTimer *)timer {
    if(![[NSApplication sharedApplication] isHidden])
        [self setNeedsDisplay:YES];
}
-(void) drawRect:(NSRect)dirtyRect {
    glClear(GL_COLOR_BUFFER_BIT);
}

1 个答案:

答案 0 :(得分:4)

您尚未表明是否要在NSOpenGLView或CAOpenGLLayer中绘制OpenGL内容。这两种方式稍有不同,可以更新其内容以显示在屏幕上。

对于NSOpenGLView,您无需在其-drawRect:方法中更新视图。事实上,我认为您不希望触发-setNeedsDisplay:刷新NSView,因为可能会产生一些开销。在我的一个应用程序中,我使用CVDisplayLink在NSOpenGLView中的自定义渲染方法中以60 FPS触发更新。这些都不会触及-drawRect:。调用[[self openGLContext] flushBuffer]时,帧会显示在屏幕上,而不是强制重绘NSView。

CAOpenGLLayers略有不同,因为您使用自定义呈现代码覆盖- drawInCGLContext:pixelFormat:forLayerTime:displayTime:。如果其-setNeedsDisplay属性设置为YES,则会响应手动asynchronous或CAOpenGLLayer本身触发此方法。它知道何时可以通过您为响应-canDrawInCGLContext:pixelFormat:forLayerTime:displayTime:而提供的布尔值来呈现新内容。

我已经使用了这两种,每种都有其优点。 CAOpenGLLayers使得在OpenGL渲染上叠加其他UI元素变得更加容易,但是它们的渲染方法很难从后台线程中正常工作。 NSOpenGLViews可以使用CVDisplayLink在后台线程上轻松更新,但是可以覆盖内容。