使用GLKit进行按需OpenGL ES渲染

时间:2011-10-12 23:25:17

标签: ios opengl-es glkit

我正在研究转换我的OpenGL渲染代码以利用GLKit的一些功能(即异步纹理加载和GLKView/Controller提供的自动化)。但是,似乎这些类的设计主要是为了适应使用动画循环渲染的人,而我正在使用按需渲染。另外,一些渲染是针对纹理而不是GLKView的帧缓冲,所以我是否应该只是将GLKView子类化并添加其他FBO?

这种类型的设置是否有推荐的方法?我期待的是:

  • 将视图控制器的preferredFramesPerSecond设置为0,或者只是 暂停框架更新?
  • 忽略glkViewControllerUpdateglkView:drawInRect:方法 当我需要它时,只需画出我需要的东西。
  • 按顺序使用视图setNeedsDisplay和普通UIView 显示框架(我需要调用bindDrawable给我 也会渲染到纹理?)。

如果这不是新API的设计,那么也许不值得努力?我希望文档比它更彻底。当API稍微“成熟”时,可能会提供更多样本......

由于

3 个答案:

答案 0 :(得分:23)

我最终使用的方法是不打扰GLKViewController,而只是直接在GLKView子类下使用UIViewController

显然,GLKViewController适用于需要为游戏等应用提供一致渲染循环的用户。没有它,绘制到GLKView就像调用[glkView setNeedsDisplay]一样简单。请务必将enableSetNeedsDisplay设置为YES以启用此行为。

如果您仍想使用GLKViewController,可以在viewWillAppear中禁用动画渲染循环,如下所示:

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];    // setPaused automatically set to NO in super's implementation

    [self setPaused:YES];
}

另外,将resumeOnDidBecomeActive设置为NO以防止视图控制器再次自动恢复。

使用普通UIViewControllerGLKView是完全可以接受的,我已经看到Apple工程师推荐它作为执行按需绘图的适当方式。

答案 1 :(得分:3)

我刚刚使用EAGLContext管理器将我的代码转换为使用GLKit类。

你建议你可以“.. {。glkView:drawInRect:方法,并在我需要的时候画出你需要的东西”。这似乎是表现明智的明智选择;我假设(虽然没有尝试过)如果你只是没有指定GLKViewDelegate或者提供一个定义了GLKView的子类drawInRect:,那么就不会出现动画循环渲染。你试过这个吗?

另一种方法是在@property (assign, nonatomic) BOOL shouldUpdate;课程中创建一些MyController : GLKViewController <GLKViewDelegate>,只有在有事情要做时才会更新:

[self setDelegate:self]; // in init or awakeFromNib or other..

-(void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
    if ([self shouldUpdate]) { ...

我确信你明白这一点,但这并不复杂。

值得一提的是:官方API文档声明viewDidLoad应在GLKViewController中用于初始GL设置。我有这个问题;出于某种原因,我的glCreateShader调用始终返回零。这可能是由于我设置了EAGLContext后初始化;我无法将其作为init参数传递,因为我在Storyboard中创建了控制器。但是,代码没有任何逻辑上的错误,所以如果您遇到类似问题,我会提供此友好警告。我的解决方案就是在drawInRect中使用以下内容:

-(void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
    if ([self initialGLSetupDone] == NO) {
        [self beforeFirstRender];
        [self setInitialGLSetupDone:YES];
    }
    // .. rest of render code goes here.
}

显然,不必要地在那里安装IF并不理想,但这是一个简单的解决方案。

如果您尝试更新以使用GLKit,请告诉我。

答案 2 :(得分:1)

创建GLKView后,添加以下行:

glkView.enableSetNeedsDisplay = TRUE;

(因此,没有人会自动重绘视图)

如果要重绘,请插入以下行:

[glkView setNeedsDisplay];

...然后drawInRect例程将只被调用一次。

希望它有所帮助。