使用Cocoa的简单OpenGL示例



我已经尝试在Objective-C中使用OpenGL制作场景好几个星期了,但似乎无法实现。我从绘制NSOpenGLView类开始:教程,这对我来说很好,我甚至可以稍微扩展一下,但OpenGL编程指南在这一步之后留下了一些漏洞。它们解释了如何将缓冲区加倍和同步刷新率等细节,但没有提供任何关于如何更新视图的实际示例。所以目前我可以在屏幕上画很多很酷的东西,但一旦出现,它就只是一个静态图像。不动,不转
有人知道一个简单的例子吗?

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

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;
}

这是我经常遇到的问题,这一关键步骤并不是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图形。

这是一个非常普遍的问题,如何最终设计渲染引擎的整个结构取决于您。要告诉你如何实现这一点需要很多,但网上有很多书和教程可以帮助你入门。

关于如何慢慢创建适合游戏的简单结构(在本例中为2D),可以在这里找到一个非常好的方法,但它是针对Win32的,所以你需要调整它,但假设你对编程有大致的理解,你应该能够理解他正在构建的总体设计。

最新更新