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

iOS OpenGL ES屏幕旋转,而后台应用程序栏可见,ios,ipad,glkit,screen-rotation,Ios,Ipad,Glkit,Screen Rotation,我的应用程序使用GLKit使用opengles渲染3D场景 除了一件事外,一切都很好。当我在iPad上启动我的应用程序并显示背景应用程序栏(双击“主页”按钮),然后更改设备的方向时,场景被错误地更新(最后渲染的图像只是拉伸以填充新的矩形) 我找到了原因。当后台应用程序栏出现时,GLKViewController的暂停将自动设置为YES(应用程序代理接收-applicationWillResignActive:),并且在关闭此栏之前不会进行渲染 我在Apple guides()中发现,在收到-ap

我的应用程序使用
GLKit
使用
opengles
渲染3D场景

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

我找到了原因。当后台应用程序栏出现时,
GLKViewController的
暂停
将自动设置为
YES
(应用程序代理接收
-applicationWillResignActive:
),并且在关闭此栏之前不会进行渲染

我在Apple guides()中发现,在收到
-applicationWillResignActive:
后,应用程序应停止GL渲染或将被终止。所以看起来一切正常,除了旋转后的不良渲染:)


我检查了一些OpenGL游戏。当该条显示时,它们也变为“暂停”,但在设备旋转时以某种方式正确更新暂停的场景。他们是如何实现这一点的?

实现委托方法(如果您还没有这样做的话)


-(void)应用程序将进入前台
,并从那里取消启动
GLKViewController


根据我从你的问题中了解到的情况,你可以暂停游戏,但也可以用这种方法调整glView的大小,但如果看不到任何代码,也很难真正看到发生了什么

tl;dr:您可能只需要将
GLKView
contentMode
设置为
UIViewContentModeRedraw

首先,我不认为你的应用程序实际上进入了后台,我认为它只是变得不活动。
applicationWillResignActive
applicationidentinterbackground
委托方法之间的区别。假设应用程序仅处于非活动状态,请使用以下命令,以防它实际置于后台,请参见下文

苹果的文档说,当调用
应用程序willresignative
时,你应该“降低OpenGL ES的帧速率”,而不是说OpenGL ES调用是不允许的,这只发生在应用程序进入后台之后


这意味着
GLKit
GLKView
/
GLKViewController
在这方面可能有点过分热心。要解决此问题,您需要确保:

  • GLKView
    contentMode
    设置为
    UIViewContentModeRedraw
  • GLKView
    drawRect
    方法即使在应用程序处于非活动状态但帧已更改时也会绘制帧,但是在应用程序处于后台时不会绘制帧(即使用OpenGL ES调用)
  • 然而,我的假设是,当应用程序在后台时,
    drawRect
    方法甚至不会被调用,因此您可能不必真正担心
    glkView:drawInRect
    委托方法中的OpenGL ES调用。但是,在您的情况下不会调用此函数的原因是视图不会失效。没有失效的原因有两个:


  • GLKViewController
    中定期使视图无效的主帧循环由
    paused
    属性暂停
  • GLKView
    contentMode
    可能是默认的“UIViewContentModesCaletFill”
  • 由于
    GLKView
    drawRect
    方法可能甚至没有查看
    paused
    属性,因此仅更改
    contentMode
    就足够了


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

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

    也就是说,在
    应用程序中,将执行以下操作:


  • 暂停游戏循环(通过设置
    GLKViewController
    paused
    完成)

  • 暂停渲染循环(通过设置
    GLKViewController
    paused
    完成)
  • 获取当前方向状态的当前帧缓冲区
  • 使用与旋转方向状态相对应的帧缓冲区和视口再次渲染当前游戏状态,并抓取该帧缓冲区
  • 此外,您需要将
    GLKView
    contentMode
    设置为
    UIViewContentModeRedraw
    ,以便在视图的框架因方向更改而更改后,实际调用
    drawRect
    方法

    最后,在
    GLKView
    drawRect
    方法中,您需要检查
    paused
    是否为
    YES
    NO
    NO
    情况下是否正常渲染,在
    YES
    案例中,使用
    applicationwillresignative
    中保存的一个帧缓冲区,并使用常规
    UIKit
    调用将其绘制到视图中


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

    GLKViewController
    在进入前台时自动取消暂停。当后台应用程序栏可见时,应用程序处于“后台”状态,这次我需要
    GLKView
    更新。@kpower我想我现在明白你的问题了。问题是,当应用程序正在运行时,您双击了home按钮。如果有控制渲染循环的计时器,则“是”,在DiEnterBackground期间使其无效,而不是willresignactive。我刚刚在模拟器中测试了我的一个项目,当应用程序栏打开时,动画确实会暂停,但是当我旋转虚拟ipad时,框架会用新的asp