iOS OpenGL ES screen rotation while background apps bar visible

前端 未结 2 1280
夕颜
夕颜 2021-02-09 05:40

My app uses GLKit to render 3D scene with OpenGL ES.

All works fine, except one thing. When I launch my app in iPad and display background apps

2条回答
  •  后悔当初
    2021-02-09 06:18

    tl;dr: possibly you only need to set the GLKView's contentMode to UIViewContentModeRedraw

    Firstly I don't think that your application actually enters into the background, I think it only becomes inactive. The distinction between the applicationWillResignActive and applicationDidEnterBackground delegate methods. Assuming that the application is only inactive use the following, in case it actually gets put in the background then see below.

    The apple documentation says that you should "throttle down OpenGL ES framerates" when applicationWillResignActive gets called, not that OpenGL ES calls are not allowed, that only happens after the application goes into the background.

    This means that GLKit's GLKView/GLKViewController may be a bit overzealous in this regard. To fix it you need to make sure that:

    1. The GLKView's contentMode is set to UIViewContentModeRedraw
    2. The GLKView's drawRect method does draw the frame even when the application is inactive but the frame is changed, but does not draw the frame (that is use OpenGL ES calls) when the application is in the background.

    However, my presumption is that the drawRect method does not even get called when the application is in the background, so you probably don't really have to worry about the OpenGL ES calls in the glkView:drawInRect delegate method. The reason however that this function does not get called in your situation is that the view does not get invalidated. The reason for not being invalidated is twofold:

    1. The main frame loop in GLKViewController that invalidates the view periodically is paused by the paused property.
    2. The GLKView contentMode is probably the default 'UIViewContetModeScaleToFill'

    As the GLKView drawRect method is probably not even looking at the paused property, just changing the contentMode may already be enough.


    I would propose the following solution if the application actually does go into the background. As you're not allowed to use OpenGL ES calls while running in the background the solution is pretty straightforward:

    Do all OpenGL ES calls you need to do to support what you want before you enter the background.

    That is, in applicationWillResignActive do the following:

    1. Pause your game loop (done by setting GLKViewController's paused)
    2. Pause your render loop (done by setting GLKViewController's paused)
    3. Grab the current framebuffer for the current orientation state
    4. Render the current game state one more time with a framebuffer and viewport that correspond to the rotated orientation state and grab that framebuffer

    Furthermore you need GLKView's contentMode to be set to UIViewContentModeRedraw so that the drawRect method is actually called after the view's frame has been changed by the orientation change.

    Finally in GLKView's drawRect method you need to check whether paused is YES or NO in the NO case do the rendering as normal, in the YES case take one of the framebuffers saved in applicationWillResignActive and draw it to the view with regular UIKit calls.

    I'm not sure how well this hackish solution would integrate with GLKit, you might need some subclassing.

提交回复
热议问题