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



我开始开发3D粒子系统编辑器和演化器。我过去用OpenGL做过类似的事情,但这次我要做一个macosx可可应用程序。我只是有几个关于我在设置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);
}

您还没有指明是在NSOpenGLView还是CAOpenGLLayer中绘制OpenGL内容。这两种更新内容以显示在屏幕上的方式略有不同。

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

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

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

最新更新