我开始研究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);
}
答案 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在后台线程上轻松更新,但是可以覆盖内容。