如何避免在iOS OpenGL ES应用程序的自动转换中出现短暂的延伸
这近来一直在困扰着我。 将一个支持纵向和横向的OpenGL ES应用程序放在一起非常简单。 但是在自动旋转过程中,系统似乎只是将渲染缓冲区强制拉伸到新维度,自动旋转,然后调用通常的-layoutSubviews
– > -resizeFromLayer:
等等,以便可以将可绘制对象调整到新的视口维度。
我见过的大多数支持纵向和横向的应用程序似乎都适合这种简单的方法。 但是我想知道我能做得更好吗?
也许我应该在它发生之前拦截自动旋转(使用UIViewController
的通常方法),一旦渲染缓冲区“扩大”到最长屏幕尺寸的完美平方(例如,iPhone 5上的1136px x 1136px) – 这样,在屏幕外出血,执行自转(没有渲染缓冲区大小的变化,因此没有拉伸,就像在两个风景方向之间切换时一样),最后再次调整帧缓冲区,以便在屏幕之外处理不可见的“浪费的”边距。 (当然,我可以一直有一个方形的帧缓冲器,但这将是低效的填充方式)
有什么build议么? 有没有更好的方法来实现这一点,我没有想过?
编辑
我修改了我的-resizeFromLayer:
代码,如下所示:
CGRect bounds = [layer bounds]; // Enlarge layer to square of the longest side: if (bounds.size.width < bounds.size.height) { bounds.size.width = bounds.size.height; } else{ bounds.size.height = bounds.size.width; } [layer setBounds:bounds]; // Adjust size to match view's layer: [_mainContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer*) [_view layer]]; // Query the new size: glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &_backingWidth); glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &_backingHeight); // (etc., you know the drill...)
…它的工作原理! 就目前来看,我一直都有一个浪费的,不出屏幕的广场渲染缓冲区,但这只是一个概念validation。 在生产代码上,我会在自动旋转之前执行所述的大小调整,然后调整回屏幕尺寸。
我设法通过从GLKView presentationLayer
获取视图大小,在3D应用程序中很容易地解决这个问题。 这将在旋转animation中给出当前的视图尺寸,并且在更新步骤中可以根据这个尺寸来计算正确的投影matrix。 这可以防止任何不正确的宽高比失真
如果你想试试这个,你可以在Xcode的OpenGL游戏模板中join以下几行:
- (void)update { // get the size from the presentation layer, so that animating does not squish CALayer *presentationLayer = [self.view.layer presentationLayer]; CGSize layerSize = presentationLayer.bounds.size; float aspect = fabsf(layerSize.width / layerSize.height); GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); ... }