使用Cocoa的简单OpenGL示例

时间:2012-03-27 22:30:19

标签: objective-c cocoa opengl

我一直试图在Objective-C中使用OpenGL创建一个场景几周,而我似乎无法让它工作。我从Drawing to an NSOpenGLView Class: A Tutorial开始,这对我来说很好,我甚至可以稍微扩展它,但是OpenGL编程指南在那一步之后留下了一些漏洞。他们解释了如何加倍缓冲和同步刷新率以及所有这些的详细信息,但是它们没有提供有关如何更新视图的任何实际示例。所以目前我可以在屏幕上绘制很多很酷的东西,但是一旦它在那里它只是一个静态图像。没有动,没有旋转。
有没有人知道一个好的,简单实例如何实现这个?

3 个答案:

答案 0 :(得分:6)

您可以尝试使用显示链接重复绘制与显示同步。设置一个:

GLint swapInt = 1;
[yourContext setValues:&swapInt forParameter:NSOpenGLCPSwapInterval]; 

CVDisplayLinkCreateWithActiveCGDisplays(&displayLink);
CVDisplayLinkSetOutputCallback(displayLink, &displayLinkCallback, self);

CGLContextObj cglContext = [yourContext CGLContextObj];
CGLPixelFormatObj cglPixelFormat = [[NSOpenGLView defaultPixelFormat] CGLPixelFormatObj];
CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(displayLink, cglContext, cglPixelFormat);

CVDisplayLinkStart(displayLink);

然后,您的回调每帧运行一次:

static CVReturn displayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* now, const CVTimeStamp* outputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* displayLinkContext)
{
    NSAutoreleasePool* pool = [NSAutoreleasePool new];
    if ([self lockFocusIfCanDraw])
    {
        //Your drawing code
        [self unlockFocus];
    }
    [pool drain];

    return kCVReturnSuccess;
}

答案 1 :(得分:3)

这是我经常遇到的一个问题,令我惊讶的是,这个关键步骤不是NSOpenGLView教程文档的一部分。

您需要设置回调计时器以通知视图需要重绘:

- (void)awakeFromNib
{
    NSTimer *updateTimer = [NSTimer timerWithTimeInterval:1.0f/30.0f target:self selector:@selector(idle:) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:updateTimer forMode:NSDefaultRunLoopMode];
}

请注意,这发生在awakeFromNib。 计时器将以1/30的间隔触发,如果您愿意,可以更改。 每次触发时,它都会调用一个名为idle的函数。这个功能可以这样实现:

- (void)idle:(NSTimer*)timer
{
    [self setNeedsDisplay:YES];
}

这会导致视图在每次更新时重绘自己,包括OpenGL图形。

答案 2 :(得分:0)

这是一个非常普遍的问题,如何最终设计渲染引擎的整个结构取决于你。告诉你如何实现它会有很多,但是有大量的书籍和教程可以在线获取。

如何慢慢创建一个适合游戏的简单结构(在这种情况下为2D)可以找到here,但它适用于Win32,所以你需要适应它,但假设你有对编程的一般理解,你应该能够理解他正在构建的一般设计。