为什么 iOS 上的 OpenGL ES 渲染会垂直翻转?

me-*_*e-- 6 c android opengl-es ios

我有一些 C 代码来渲染一些 OpenGL 内容,它可以在 Android 和 iOS 上运行。在 Android 上看起来不错。但在 iOS 上它是垂直翻转的。

下面是一些简单的代码来演示(因为OpenGL C代码很啰嗦,所以只复制了相关部分):

GLfloat vVertices[] = {
    0.0f,  0.5f,
    -0.5f, -0.5f,
    0.5f, -0.5f
};

glViewport(0, 0, context->width, context->height);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(data->programObject);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vVertices);
glEnableVertexAttribArray(0);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(0);
Run Code Online (Sandbox Code Playgroud)

在 Android 上它看起来像这样:

在此输入图像描述

但在 iOS 上它看起来像这样:

在此输入图像描述

两个平台之间唯一的区别是 OpenGL ES 的初始化代码,因为所有 OpenGL 代码都是共享的 C 代码。但是,我看不出初始化代码有任何明显的错误。

这是初始化代码(我删除了大部分错误处理,因为除了我留下的错误之外,没有任何错误被触发):

- (void)initGL {
    _context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];

    [EAGLContext setCurrentContext:_context];
    [self createCVBufferWithSize:_renderSize withRenderTarget:&_target withTextureOut:&_texture];

    glBindTexture(CVOpenGLESTextureGetTarget(_texture), CVOpenGLESTextureGetName(_texture));

    glTexImage2D(GL_TEXTURE_2D,         // target
                 0,                     // level
                 GL_RGBA,               // internalformat
                 _renderSize.width,     // width
                 _renderSize.height,    // height
                 0,                     // border
                 GL_RGBA,               // format
                 GL_UNSIGNED_BYTE,      // type
                 NULL);                 // data
    // HACK: we always get an "error" here (GL_INVALID_OPERATION) despite everything working. See /sf/ask/3997282341/
    glGetError();

    glGenRenderbuffers(1, &_depthBuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, _depthBuffer);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, _renderSize.width, _renderSize.height);
    glGenFramebuffers(1, &_frameBuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffer);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, CVOpenGLESTextureGetName(_texture), 0);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthBuffer);

    if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
        NSLog(@"failed to make complete framebuffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER));
    } else {
        NSLog(@"Successfully initialized GL");
        char* glRendererName = getGlRendererName();
        char* glVersion = getGlVersion();
        char* glShadingLanguageVersion = getGlShadingLanguageVersion();

        NSLog(@"OpenGL renderer name: %s, version: %s, shading language version: %s", glRendererName, glVersion, glShadingLanguageVersion);
    }
}
Run Code Online (Sandbox Code Playgroud)

这是创建实际纹理的代码(使用 EAGL):

- (void)createCVBufferWithSize:(CGSize)size
              withRenderTarget:(CVPixelBufferRef *)target
                withTextureOut:(CVOpenGLESTextureRef *)texture {

    CVReturn err = CVOpenGLESTextureCacheCreate(kCFAllocatorDefault, NULL, _context, NULL, &_textureCache);

    if (err) return;

    CFDictionaryRef empty;
    CFMutableDictionaryRef attrs;
    empty = CFDictionaryCreate(kCFAllocatorDefault,
                               NULL,
                               NULL,
                               0,
                               &kCFTypeDictionaryKeyCallBacks,
                               &kCFTypeDictionaryValueCallBacks);

    attrs = CFDictionaryCreateMutable(kCFAllocatorDefault, 1,
                                      &kCFTypeDictionaryKeyCallBacks,
                                      &kCFTypeDictionaryValueCallBacks);

    CFDictionarySetValue(attrs, kCVPixelBufferIOSurfacePropertiesKey, empty);
    CVPixelBufferCreate(kCFAllocatorDefault, size.width, size.height,
                        kCVPixelFormatType_32BGRA, attrs, target);

    CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
                                                 _textureCache,
                                                 *target,
                                                 NULL, // texture attributes
                                                 GL_TEXTURE_2D,
                                                 GL_RGBA, // opengl format
                                                 size.width,
                                                 size.height,
                                                 GL_BGRA, // native iOS format
                                                 GL_UNSIGNED_BYTE,
                                                 0,
                                                 texture);

    CFRelease(empty);
    CFRelease(attrs);
}
Run Code Online (Sandbox Code Playgroud)

谁能告诉我为什么iOS会这样翻转?此后我注意到其他人也有同样的问题,例如这里,但尚未找到解决方案。