8

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

我见过的大多数同时支持纵向和横向的应用程序似乎都适合这种简单的方法。但我想知道我是否可以做得更好...

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

有什么建议么?有没有更好的方法来实现我没有想到的?

编辑

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

...它的工作原理!就目前而言,我一直有一个浪费的、屏幕外出血的方形渲染缓冲区,但这只是一个概念证明。在生产代码中,我会在自动旋转之前执行上述调整大小到正方形,然后再调整回屏幕尺寸。

4

1 回答 1

6

通过从 GLKView 获取视图大小,我设法在我的 3D 应用程序中相当容易地解决了这个问题 presentationLayer。这将在旋转动画期间给出当前视图大小,并且可以在更新步骤期间基于此大小计算正确的投影矩阵。这可以防止任何不正确的纵横比失真。

如果你想试试这个,你可以在 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);

    ...
}
于 2013-09-11T13:05:16.153 回答