ios – – [EAGLContext renderbufferStorage:fromDrawable:]第二次失败?

我正在开发一个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,_depthBuffer);

        // Attach to stencil:
        glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_STENCIL_ATTACHMENT,_depthBuffer);
    }
    else{
        // Depth only

        // Allocate storage:
        glRenderbufferStorage(GL_RENDERBUFFER,GL_DEPTH_COMPONENT24_OES,_backingHeight);

        // Attachto depth:
        glFramebufferRenderbuffer(GL_FRAMEBUFFER,_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,_transDepthBuffer);

        // Attach to stencil:
        glFramebufferRenderbuffer(GL_FRAMEBUFFER,_transDepthBuffer);
    }
    else{
        // Allocate storage
        glRenderbufferStorage(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_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,GL_RGBA,_backingHeight,GL_UNSIGNED_BYTE,0);

        // Attach:
        glFramebufferTexture2D(GL_FRAMEBUFFER,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的-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,&_backingHeight);

    // 2. Resize depth buffer
    bindRenderbuffer(_depthBuffer);

    if (_useStencilBuffer) {
        // (Depth & Stencil)

        glRenderbufferStorage(GL_RENDERBUFFER,_backingHeight);
    }
    else{
        // (Depth only)

        glRenderbufferStorage(GL_FRAMEBUFFER,_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,_backingHeight);
    }
    else{
        glRenderbufferStorage(GL_RENDERBUFFER,_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,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,_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:failed;这次是在-createFramebuffers中).

现在,我只返回YES(我的应用只支持肖像,所以实际上没有发生屏幕尺寸变化),但我真的想修复它,因为有一天我需要支持景观等…

解决方法

renderbufferStorage:fromDrawable:失败的一个可能原因是_mainContext不是当时的当前上下文.尽管似乎没有其他上下文可以窃取“当前”状态,但我建议在对该上下文关联的对象上运行的任何gl或EAGL代码之前调用[EAGLContext setCurrentContext:_mainContext](例如,在resizeFromLayer的开头:方法).

相关文章

当我们远离最新的 iOS 16 更新版本时,我们听到了困扰 Apple...
欧版/美版 特别说一下,美版选错了 可能会永久丧失4G,不过只...
一般在接外包的时候, 通常第三方需要安装你的app进行测...
前言为了让更多的人永远记住12月13日,各大厂都在这一天将应...