如何避免iOS OpenGL ES应用程序自动旋转的瞬间延伸

时间:2013-09-09 03:04:55

标签: ios opengl-es aspect-ratio auto-rotation

这最近一直困扰着我。将一个支持纵向和横向的OpenGL ES应用程序组合在一起非常简单。 但在自动旋转期间,系统似乎只是将渲染缓冲区强制拉伸到新的尺寸一次,自动旋转,然后调用通常的-layoutSubviews - > -resizeFromLayer:等等,因此可以将drawables调整为新的视口尺寸。

我见过的大多数支持肖像和风景的应用似乎都适合这种简单的方法。但我想知道我能不能做得更好......

也许我应该在它发生之前拦截自转(使用UIViewController的常用方法),一旦渲染缓冲区“扩展”到最长屏幕尺寸的完美平方(例如,iPhone上的1136px x 1136px) 5) - 使它“脱离”屏幕,执行自动旋转(没有渲染缓冲区尺寸变化,因此没有拉伸,就像在两个横向方向之间切换时一样),最后再次调整帧缓冲区以处置隐形,“浪费屏幕边缘? (当然我可以一直有一个方形的帧缓冲,但这样填充效率会很低)

有什么建议吗?有没有更好的方法来实现这个我没想过的?

修改

我修改了我的-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...)

......它有效!就目前而言,我一直有一个浪费的,屏幕外的方形渲染缓冲区,但这只是一个概念证明。 在生产代码上,我会在自动旋转之前执行所谓的调整大小,然后调整大小到屏幕尺寸。

1 个答案:

答案 0 :(得分:6)

我设法通过从GLKView presentationLayer获取视图大小,在我的3D应用中轻松修复此问题。这将在旋转动画期间给出当前视图大小,并且可以在更新步骤期间基于该大小计算正确的投影矩阵。这可以防止任何不正确的宽高比失真。

如果您想尝试此操作,可以将以下行添加到Xcode中的OpenGL游戏模板中:

- (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);

    ...
}