2013-08-20 27 views
8

Pracuję nad aplikacją openGL ES iOS.- [EAGLContext renderbufferStorage: fromDrawable:] Niepowodzenie po raz drugi?

Robię zwykłe rzeczy EAGLView/ES2Render.

Na starcie, tworzenie frambuffer powiedzie, stosując następujący kod:

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

Wkrótce potem UIView „s -layoutSubviews nazywa a ja z kolei wykonać -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; 
} 

Nic z tego, co "Robię to jest wyjątkowe. Mam osobny framebuffer do renderowania przejść scenicznych, z dwoma teksturami do dołączenia do koloru i głębokości.

Drugi raz -renderbufferStorage:fromDrawable: nazywa (-layoutSubviews ->resizeFromLayer:), to nie zawsze (zwraca NO); Dzwonienie pod numer glGetError() tuż przed tym skutkuje brakiem błędu, ale wywołanie go zaraz po zwrocie GL_INVALID_OPERATION. Jeśli zignoruję to i kontynuuję, glGetRenderbufferParameteriv() nadal pobiera mi odpowiednią szerokość i wysokość (odpowiednio 640 i 1136 na iPhonie 5), ale glCheckFramebufferStatus() zwróci GL_FRAMEBUFFER_UNSUPPORTED.

Alternatywnie, pominąłem powyższy resizeFromLayer: i zastąpił go w ten sposób:

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

    return [self createFramebuffers]; 
} 

... ale ten sam błąd nie ustępuje (-renderStorage:fromDrawable: nie, tym razem wewnątrz -createFramebuffers).

Na razie wracam tylko YES (moja aplikacja obsługuje tylko portret, więc żadna zmiana rozmiaru ekranu nigdy się nie dzieje), ale naprawdę chcę to naprawić, ponieważ pewnego dnia będę potrzebować obsługi krajobrazu itp.

+0

Niedawno napotkał ten problem, ale tylko wtedy, gdy uruchomiony na urządzeniu iOS 7 (nie symulator). Niestety nie wiem, co go spowodowało, ale ponowne uruchomienie urządzenia okazało się naprawić problem. Bardzo irytujące i nie ma gwarancji, że to się więcej nie powtórzy ... – Stuart

Odpowiedz

1

Jeden możliwe powodem, że renderbufferStorage:fromDrawable: zawodzi to, że _mainContext nie jest obecny kontekst w tym czasie. Chociaż może się wydawać, że żaden inny kontekst nie mógł wykraść stanu "bieżącego", polecam wywołanie [EAGLContext setCurrentContext:_mainContext] przed dowolnym kodem gl lub , który działa na obiektach powiązanych z tym kontekstem (np. Na początku metody resizeFromLayer:).

1

Innym możliwym powodem jest to, że rozmiar twojej warstwy jest zbyt duży. Ponadto upewnij się, że za każdym razem używasz nowego bufora ramki i bufora renderowania. I zniszczyłeś swoje stare przed stworzeniem nowych.

Można usunąć je jak tego

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 
} 
Powiązane problemy