我正在开发一个 iOS openGL ES 应用程序。
我正在做通常的 EAGLView / ES2Render 的东西。
启动时,frambuffer 创建成功,使用以下代码:
- (BOOL) createFramebuffers
{
    [EAGLContext setCurrentContext:_mainContext];
    // [ A ] On-screen  
    // 1. Framebuffer
    glGenFramebuffers(1, &_mainFramebuffer);
    bindFramebuffer(_mainFramebuffer);
    // 2. Color buffer
    glGenRenderbuffers(1, &_mainColorbuffer);
    bindRenderbuffer(_mainColorbuffer);
    // Adjust size to view's layer:
    CAEAGLLayer* layer = (CAEAGLLayer*)[_view layer];
    if (![_mainContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:layer]) {
        // something went horribly wrong
        NSLog(@"-[ES2Renderer createFramebuffers]: Failed to obtain renderbuffer storage from layer!");
        return NO;
    }
    // Query new size:
    glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH,  &_backingWidth);
    glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &_backingHeight);
    // Attach to color:
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _mainColorbuffer);
    // 3. Depth buffer
    glGenRenderbuffers(1, &_depthBuffer);
    bindRenderbuffer(_depthBuffer);
    if (_useStencilBuffer) {
        // Depth + Stencil
        // Allocate storage:
        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, _backingWidth, _backingHeight);
        // Attach to depth:
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthBuffer);
        // Attach to stencil:
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _depthBuffer);
    }
    else{
        // Depth only
        // Allocate storage:
        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24_OES, _backingWidth, _backingHeight);
        // Attachto depth:
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthBuffer);
    }
    // 4. Validate the set:
    GLenum framebufferStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    if (framebufferStatus != GL_FRAMEBUFFER_COMPLETE) {
        // Something went wrong!
        NSLog(@"-[ES2Renderer createFramebuffers]: Failed to make complete framebuffer object: %@",
              [self stringFromFramebufferStauts:framebufferStatus]);
        return NO;
    }
    // [ B ] Off-screen (Render-to-texture)
    // 1. Framebuffer
    glGenFramebuffers(1, &_transFramebuffer);
    bindFramebuffer(_transFramebuffer);
    // 2. Depth buffer
    glGenRenderbuffers(1, &_transDepthBuffer);
    bindRenderbuffer(_transDepthBuffer);
    if (_useStencilBuffer) {
        // Allocate storage:
        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, _backingWidth, _backingHeight);
        // Attach to depth:
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _transDepthBuffer);
        // Attach to stencil:
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _transDepthBuffer);
    }
    else{
        // Allocate storage
        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24_OES, _backingWidth, _backingHeight);
        // Attach to depth:
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _transDepthBuffer);
   }
    // 3. Textures (color buffers)
    GLuint* texPtrs[2] = {&_transTexture1, &_transTexture2};
    for (NSUInteger i=0; i < 2; i++) {
        GLuint* texPtr = texPtrs[i];
        // Create:
        glGenTextures(1, texPtr);
        // Bind:
        bindTexture2D(*texPtr);
        // Configure for pixel-aligned use:
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        // Allocate storage:
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _backingWidth, _backingHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
        // Attach:
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *texPtr, 0);
        framebufferStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
        // Validate:
        if ( framebufferStatus != GL_FRAMEBUFFER_COMPLETE) {
            // Something went wrong!
            NSLog(@"-[ES2Renderer createFramebuffers]: Failed to make complete framebuffer object: %@",
                  [self stringFromFramebufferStauts:framebufferStatus]);
            return NO;
        }
    }
    // Final State:
    bindFramebuffer(_mainFramebuffer);
    bindRenderbuffer(_mainColorbuffer);
    bindTexture2D(0);
    NSLog(@"-[ES2Renderer createFramebuffers] Succeeded.");
    return YES;
}
不久之后,UIView's-layoutSubviews被调用,我依次执行-resizeFromLayer::
- (BOOL) resizeFromLayer:(CAEAGLLayer *)layer
{
    // [ A ] On screen framebuffer
    bindFramebuffer(_mainFramebuffer);
    // 1. Resize color buffer
    bindRenderbuffer(_mainColorbuffer);
    if (![_mainContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:layer]) {
        // Something went wrong
        return NO; // <-- SECOND TIME ON, THIS HAPPENS
    }
    // Query new size:
    glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH,  &_backingWidth);
    glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &_backingHeight);
    // 2. Resize depth buffer
    bindRenderbuffer(_depthBuffer);
    if (_useStencilBuffer) {
        // (Depth & Stencil)
        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, _backingWidth, _backingHeight);
    }
    else{
        // (Depth only)
        glRenderbufferStorage(GL_FRAMEBUFFER, GL_DEPTH_COMPONENT24_OES, _backingWidth, _backingHeight);
    }
    // ...Validate:
    GLenum framebufferStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    if (framebufferStatus != GL_FRAMEBUFFER_COMPLETE) {
        // Something went wrong!
        NSLog(@"-[ES2Renderer resizeFromLayer:]: Failed to make complete framebuffer object: %@",
              [self stringFromFramebufferStauts:glCheckFramebufferStatus(GL_FRAMEBUFFER)]);
        return NO;
    }
    // [ B ] Off screen (render-to-terxture) framebuffer
    bindFramebuffer(_transFramebuffer);
    // 1. Resize depth buffer
    bindRenderbuffer(_transDepthBuffer);
    if (_useStencilBuffer) {
        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, _backingWidth, _backingHeight);
    }
    else{
        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24_OES, _backingWidth, _backingHeight);        
    }
    // 2. Resize textures
    GLuint* texPtrs[2] = {&_transTexture1, &_transTexture2};
    for (NSUInteger i=0; i < 2; i++) {
        GLuint* texPtr = texPtrs[i];
        // Bind:
        bindTexture2D(*texPtr);
        // Configure for pixel-aligned use:
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        // Allocate storage:
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _backingWidth, _backingHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
        // Attach:
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *texPtr, 0);
        // Validate:
        if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
            // Something went wrong!
            NSString* statusString = [self stringFromFramebufferStauts:glCheckFramebufferStatus(GL_FRAMEBUFFER)];
            NSLog(@"-[ES2Renderer resizeFromLayer:]: Failed to make complete framebuffer object: %@", statusString);
            return NO;
        }
    }
    bindFramebuffer(_mainFramebuffer);
    bindRenderbuffer(_mainColorbuffer);
    // Pass new ortho projection to shaders
    [self initializeModelViewMatrix];
    [self initializeSpriteProgram];
    // Set new viewport
    glViewport(0, 0, _backingWidth, _backingHeight);
    NSLog(@"-[ES2Renderer resizeFromLayer:]: Succeeded.");
    return YES;
}
我所做的一切都没有什么特别的。我有一个单独的帧缓冲区来渲染场景转换,有两个纹理可以附加到颜色和深度上。
第二次-renderbufferStorage:fromDrawable:调用(-layoutSubviews-> resizeFromLayer:),它总是失败(返回NO);在此之前调用glGetError()不会导致错误,但在返回之后立即调用它GL_INVALID_OPERATION。如果我忽略这一点并继续,glGetRenderbufferParameteriv()仍然会得到正确的宽度和高度(在 iPhone 5 上分别为 640 和 1136),但glCheckFramebufferStatus()会返回GL_FRAMEBUFFER_UNSUPPORTED.
或者,我跳过了上面的resizeFromLayer:内容并将其替换为:
- (BOOL) resizeFromLayer:(CAEAGLLayer *)layer
{
    [self destroyFramebuffers];
    return [self createFramebuffers];
}
...但同样的错误仍然存在(-renderStorage:fromDrawable:失败;这次在里面-createFramebuffers)。
现在,我刚回来YES(我的应用只支持纵向,所以实际上没有发生屏幕尺寸变化),但我真的很想修复它,因为有一天我需要支持横向等......