2013-08-20 25 views
8

iOS openGL ES uygulaması geliştiriyorum.- [EAGLContext renderbufferStorage: fromDrawable:] İkinci kez açma başarısız mı?

Normal EAGLView/ES2Render öğelerini yapıyorum. UIView 'ın -layoutSubviews denir ve ben sırayla -resizeFromLayer: yürütmek Kısa bir süre sonra

- (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; 
} 

,: Başlangıçta

, frambuffer oluşturma Aşağıdaki kodu kullanarak, başarılı neyin

- (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; 
} 

Hiçbir şey Yapmak özeldir. Renklere ve derinliğe bağlı iki doku ile sahne geçişlerini işlemek için ayrı bir çerçeveleyicim var.

-renderbufferStorage:fromDrawable: olarak adlandırılan ikinci kez (-layoutSubviews ->resizeFromLayer:), bu her zaman başarısız (NO döner); Bundan hemen önce glGetError() numaralı telefonu arayarak hata yapmazsınız, ancak GL_INVALID_OPERATION geri döndükten sonra hemen çağırır. Bunu göz ardı edip devam edersem glGetRenderbufferParameteriv() hala bana doğru genişlik ve yüksekliği (iPhone 5 üzerinde sırasıyla 640 ve 1136) alır, ancak glCheckFramebufferStatus()GL_FRAMEBUFFER_UNSUPPORTED'u döndürür.

- (BOOL) resizeFromLayer:(CAEAGLLayer *)layer 
{ 
    [self destroyFramebuffers]; 

    return [self createFramebuffers]; 
} 

... aynı hata devam (; bu kez -createFramebuffers içinde -renderStorage:fromDrawable: başarısız):

Alternatif olarak, yukarıdaki resizeFromLayer: atlanır ve bu ile değiştirilir.

Şimdilik, sadece YES'u döndürüyorum (uygulamam yalnızca portre özelliğini destekliyor, dolayısıyla hiçbir ekran boyutu değişikliği gerçekleşmiyor), ama gerçekten düzeltmek istiyorum çünkü bir gün manzarayı desteklemem gerekecek ... renderbufferStorage:fromDrawable: başarısız olduğunu

+0

gibi onları silmek, ancak iOS 7 cihazda çalışan yalnızca (simülatör) biçimde. Ne yazık ki neden kaynaklandığını bilmiyorum, ancak aygıtı yeniden başlatmak sorunu çözmek için ortaya çıktı. Yine de çok sinir bozucu ve tekrar olmayacağını garanti etmez ... – Stuart

cevap

1

bir mümkün nedeni _mainContext o zaman şimdiki bağlam olmadığıdır. Başka bir bağlamın 'geçerli' durumunu çalmadığı görünse bile, bu bağlamla ilişkili nesneler üzerinde çalışan herhangi bir gl veya EAGL kodundan önce [EAGLContext setCurrentContext:_mainContext] numaralı telefonu çağırmanızı öneririz (ör. resizeFromLayer: yönteminin başlangıcında).

1

Başka bir olası neden, katmanınızın boyutunun çok büyük olmasıdır. Ayrıca, her seferinde yeni bir framebuffer ve renderbuffer kullandığınızdan emin olun. Ve yenilerini yaratmadan önce eskilerini yok ettin.

Sen Geçenlerde bu sorunla karşılaştı bu

if let displayFramebuffer = self.displayFramebuffer { 
    var temporaryFramebuffer = displayFramebuffer 
    glDeleteFramebuffers(1, &temporaryFramebuffer) 
    self.displayFramebuffer = nil 
} 

if let displayRenderbuffer = self.displayRenderbuffer { 
    var temporaryRenderbuffer = displayRenderbuffer 
    glDeleteRenderbuffers(1, &temporaryRenderbuffer) 
    self.displayRenderbuffer = nil 
}