iOS OpenGL:为什么缩放我的视网膜渲染缓冲区会缩小我的图像,我该如何解决?

iOS OpenGL: Why has scaling my renderbuffer for retina shrunk my image, and how do I fix it?

我正在使用 Retina iPad 进行增强现实项目,但两层 - 相机源和 OpenGL 覆盖层 - 没有使用高分辨率屏幕。相机源被绘制到一个纹理,该纹理似乎正在缩放和采样,其中叠加使用块状 4 像素放大:

我查看了一堆问题并将以下行添加到我的 EAGLView class。

到initWithCoder,在调用setupFrameBuffer和setupRenderBuffer之前:

    self.contentScaleFactor = [[UIScreen mainScreen] scale];

并在 setupFrameBuffer 中

float screenScale = [[UIScreen mainScreen] scale];
float width = self.frame.size.width;
float height = self.frame.size.height;

glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width * screenScale, height * screenScale);
...
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width*screenScale, height*screenScale, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);

最后两行只是修改为包含比例因子。

运行 这段代码给出了以下结果:

如您所见,图片现在只填满了屏幕的左下四分之一,但我可以确认图片只是缩放了,没有被裁剪。谁能帮我弄清楚这是为什么?

它实际上并没有被缩放,而是您实际上是将帧绘制到您在允许渲染缓冲区在两个方向上都是 2 倍大小之前定义的定义大小。

最有可能发生的事情是您根据像素而不是更通用的 OpenGL 坐标 space 定义尺寸,它在 x 和 y 方向上从 -1 移动到 1(这确实是当你在 2D 中工作时,就像你一样)。

此外,呼叫:

float width = self.frame.size.width;
float height = self.frame.size.height;

将 return 不是视网膜尺寸的尺寸。如果你 NSLog 那些,你会看到即使在基于视网膜的设备上,那些 return 值基于非基于视网膜的屏幕,或者更一般地说是运动单位,而不是像素。

我选择获取视图实际大小(以像素为单位)的方式是:

GLint myWidth  = 0;
GLint myHeight = 0;

glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES,  &myWidth);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &myHeight);

在 iOS 中,我一直使用以下代码作为我的设置:

-(void)setupView:(GLView*)theView{
    const GLfloat zNear = 0.00, zFar = 1000.0, fieldOfView = 45.0;
    GLfloat size;
    glEnable(GL_DEPTH_TEST);
    glMatrixMode(GL_PROJECTION);
    size = zNear * tanf(DEGREES_TO_RADIANS(fieldOfView) / 2.0);

    //CGRect rect = theView.bounds;
    GLint width, height;

    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &width);
    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &height);

    // NSLog(@"setupView rect width = %d, height = %d", width, height);

    glFrustumf(-size, size, -size / ((float)width / (float)height), size /
           ((float)width / (float)height), zNear, zFar);
    glViewport(0, 0, width, height);
    glMatrixMode(GL_MODELVIEW);

    glLoadIdentity();

}

上面的例程在我正在测试视网膜和非视网膜设置的代码中使用,并且工作正常。此 setupView 例程在 viewController.

中是可重写的

这是我找到的解决方案。

我发现在我的绘图函数中我设置了基于 glview.bounds.size 的 glViewport 大小,它以点而不是像素为单位。将其切换为基于 framebufferWidth 和 framebufferHeight 的设置解决了这个问题。

   glViewport(0, 0, m_glview.framebufferWidth, m_glview.framebufferHeight);