iOS OpenGL ES屏幕旋转,而后台应用栏可见

时间:2012-12-19 14:55:12

标签: ios ipad glkit screen-rotation

我的应用使用GLKit使用OpenGL ES渲染3D场景。

一切正常,除了一件事。当我在iPad中启动我的应用程序并显示后台应用程序栏(单击双击“主页”按钮)然后更改设备的方向时,场景会被错误更新(最后渲染的图像只是拉伸以填充新的矩形)。

我找到了原因。当后台应用栏显示时,GLKViewController's paused会自动设置为YES(应用代理接收-applicationWillResignActive:),并且在此栏关闭之前不会进行渲染。

我在Apple指南(OpenGL ES Programming Guide for iOS / Implementing a Multitasking-aware OpenGL ES Application)中发现,在收到-applicationWillResignActive:申请后,应停止GL渲染或终止。所以似乎一切都好,除了旋转后的坏渲染:)

我检查了一些OpenGL游戏。当显示此栏时,它们也会“暂停”,但不知何故正确更新设备旋转时暂停的场景。他们是如何实现这一目标的?

2 个答案:

答案 0 :(得分:2)

tl; dr:您可能只需要将GLKView的{​​{1}}设置为contentMode

首先,我不认为您的应用程序实际进入后台,我认为它只会变为非活动状态。 UIViewContentModeRedrawapplicationWillResignActive委托方法之间的区别。假设应用程序仅处于非活动状态,请使用以下内容,以防它实际放入后台,请参阅下文。

Apple文档说,当applicationDidEnterBackground被调用时,你应该“降低OpenGL ES帧率”,而不是不允许OpenGL ES调用,只有在应用程序进入后台后才会发生。

这意味着applicationWillResignActive的{​​{1}} / GLKit在这方面可能有点过分热心。要修复它,您需要确保:

  1. GLKView的{​​{1}}设置为GLKViewController
  2. 即使应用程序处于非活动状态但框架已更改,GLKView的{​​{1}}方法确实也会绘制框架,但不会当应用程序在后台时绘制框架(即使用OpenGL ES调用)。
  3. 但是,我的假设是,当应用程序在后台时,contentMode方法甚至不会被调用,因此您可能不必担心{{1}中的OpenGL ES调用委托方法。然而,在您的情况下不调用此函数的原因是视图不会失效。不被无效的原因有两个:

    1. UIViewContentModeRedraw中的主框架循环定期使视图无效,暂停GLKView属性。
    2. drawRect drawRect可能是默认的'UIViewContetModeScaleToFill'
    3. 由于glkView:drawInRect GLKViewController方法可能甚至没有查看paused属性,只更改GLKView可能已经足够了。


      如果应用程序确实进入后台,我会建议以下解决方案。由于您不允许在后台运行时使用OpenGL ES调用,因此解决方案非常简单:

      在您进入后台之前,您需要执行所有OpenGL ES调用以支持您想要的内容。

      也就是说,在contentMode中执行以下操作:

      1. 暂停游戏循环(通过设置GLKView的{​​{1}})
      2. 完成
      3. 暂停渲染循环(通过设置drawRect的{​​{1}})
      4. 来完成
      5. 抓取当前帧缓冲区的当前方向状态
      6. 使用与旋转方向状态对应的帧缓冲区和视口再次渲染当前游戏状态并抓取该帧缓冲区
      7. 此外,您需要将paused的{​​{1}}设置为contentMode,以便在视图的框架因方向更改而更改后实际调用applicationWillResignActive方法

        最后,在GLKViewController的{​​{1}}方法中,您需要检查paused案例中的GLKViewControllerpaused还是GLKView。正常渲染,在contentMode情况下,使用UIViewContentModeRedraw中保存的一个帧缓冲区,并通过常规drawRect调用将其绘制到视图中。

        我不确定这个hackish解决方案与GLKView的集成程度如何,您可能需要一些子类化。

答案 1 :(得分:0)

实施委托方法(如果你还没有这样做)

-(void)applicationWillEnterForeground并从那里取消暂停GLKViewController

从我对你的问题的理解,你可以保持游戏暂停,但也可以在这个方法中调整glView的大小,但是没有看到任何代码也很难真正看到正在发生的事情。