代码之家  ›  专栏  ›  技术社区  ›  westsider

OpenGL ES、iPhone和间歇性错误:GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES(0x8CD6)

  •  3
  • westsider  · 技术社区  · 14 年前

    我在iPhone 4上看到这个错误,但在iPad上没有,这可能是很重要的。

    大多数情况下,这很有效。但是,我从createFrameBuffer方法中的glCheckFramebufferStatusOES()获取GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES。原因是backingWidth和backingHeight都是0。

    这是我的createFrameBuffer方法-它大部分时间都在工作。

    - (BOOL)createFramebuffer
     { 
     // Generate IDs for a framebuffer object and a color renderbuffer
     glGenFramebuffersOES(1, &viewFramebuffer);
     glGenRenderbuffersOES(1, &viewRenderbuffer);
    
     glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
    
     glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
    
     // This call associates the storage for the current render buffer with the EAGLDrawable (our CAEAGLLayer)
     // allowing us to draw into a buffer that will later be rendered to screen wherever the layer is (which corresponds with our view).
     [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(id<EAGLDrawable>)self.layer];
    
     glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
    
     //DLog(@" backing size = (%d, %d)", backingWidth, backingHeight);
     glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
     glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
     DLog(@" backing size = (%d, %d)", backingWidth, backingHeight);
    
    
     err = glGetError();
     if (err != GL_NO_ERROR)
      DLog(@"Error. glError: 0x%04X", err);
    
     // For this sample, we also need a depth buffer, so we'll create and attach one via another renderbuffer.
     glGenRenderbuffersOES(1, &depthRenderbuffer);
     glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
     glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, backingWidth, backingHeight);
    
     glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
    
     if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES)
      {
      NSLog(@"failed to make complete framebuffer object 0x%X", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
      return NO;
      }
    
     return YES;
     }
    

    2 回复  |  直到 14 年前
        1
  •  7
  •   Tom Andersen    14 年前

    我也有同样的问题。对我来说,修复方法是在去年的opengl示例代码中,苹果在每次layoutSubviews调用中重建renderbuffer。现在,如果您创建一个iPhone模板opengl项目,您将看到layoutSubviews只会破坏renderbuffer。然后在每次绘制时,如果渲染缓冲区为零,则创建它。这是更好的,因为当你要画所有的炉等都应该是发光和准备去。

    我认为,在我的例子中,渲染缓冲区是在EagleView层不可用时(即处于某种可拆卸状态)尝试构建的。在任何情况下,当我改变我的代码,以匹配它的工作。

    此外,对这段代码的调用更少,这可能更快。启动时会有很多场景加载和移动,这会用我的应用程序生成1/2打布局子视图调用。

    由于苹果代码中的注释很少,layoutsubviews调用中有一个注释非常重要:

    // The framebuffer will be re-created at the beginning of the next 
       setFramebuffer method call.
    

    --汤姆

        2
  •  0
  •   gulchrider    14 年前

    您要做的是在drawView调用中创建帧缓冲区,正如Tom上面所说,但是,您还需要将对drawView的调用推迟到layoutSubviews函数返回。我这样做的方式是:

    - (void) layoutSubviews
    {
     [EAGLContext setCurrentContext:context];
    
     [self destroyFramebuffer];
    
     // Create the framebuffer in drawView instead as needed, as before create 
     // would occasionally happen when the view wasn't servicable (?) and cause 
     // a crash. Additionally, send the drawView call to the main UI thread 
     // (ALA PostMessage in Win32) so that it is deferred until this function 
     // returns and the message loop has a chance to process other stuff, etc 
     // so the EAGLView will be ready to use when createFramebuffer is finally 
     // called and the glGetRenderbufferParameterivOES calls to get the backing 
     // width and height for the render buffer will always work (occasionally I 
     // would see them come back as zero on my old first gen phone, and this 
     // crashes OpenGL.)
     //
     // Also, using this original method, I would see memory warnings in the 
     // debugger console window with my iPad when rotating (not all the time, 
     // but pretty frequently.)  These seem to have gone away using this new 
     // deferred method...
     [self performSelectorOnMainThread:@selector(drawView) 
                            withObject:nil 
                         waitUntilDone:NO];
    }
    

    罗斯