2011-09-06 15 views
9

Per migliorare le prestazioni della mia applicazione OpenGL ES per l'iPad, stavo progettando di disegnare un elemento raramente aggiornato ma rendertime-pesante a una trama , quindi posso usare la texture solo se l'elemento deve essere ridisegnato. Tuttavia, mentre la texture è mappata correttamente sia sul simulatore che sul dispositivo, solo il simulatore è qualcosa che viene effettivamente rappresentato nella texture.Rendering su texture su iOS OpenGL ES-funziona su simulatore, ma non sul dispositivo

Quanto segue è il codice che ho aggiunto al progetto. Durante l'impostazione della scena, creo i buffer e la consistenza necessaria:

int width = 768; 
int height = 270; 

// Prepare texture for off-screen rendering. 
glGenTextures(1, &wTexture); 
glBindTexture(GL_TEXTURE_2D, wTexture); 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE); 
glClearColor(.9f, .3f, .6f, 1.0f); // DEBUG 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, 
    GL_UNSIGNED_BYTE, 0); 
glBindTexture(GL_TEXTURE_2D, 0); 

// Depth attachment buffer, always needed. 
glGenRenderbuffersOES(1, &wDepth); 
glBindRenderbufferOES(GL_RENDERBUFFER_OES, wDepth); 
glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, 
    width, height); 
glBindRenderbufferOES(GL_RENDERBUFFER_OES, 0); 

// Create FBO for render-to-texture. 
glGenFramebuffersOES(1, &wBuffer); 
glBindFramebufferOES(GL_FRAMEBUFFER_OES, wBuffer); 
glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, 
    GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, wTexture, 0); 
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, 
    GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, wDepth); 
glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0); 

A glFramebufferStatusOES sul nuovo FBO (prima che sia non legato ovviamente) produce un valore di ritorno 'framebuffer completo' sia sul simulatore e il dispositivo. Nota che ho impostato il colore rosa per la texture per confermare che la texture sia effettivamente renderizzata, e il problema è in realtà semplicemente che la texture non viene mai disegnata.

Ogni volta che la trama deve essere ridisegnato, lo faccio prima del rendering dell'elemento:

glBindFramebufferOES(GL_FRAMEBUFFER_OES, wBuffer); 
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
glViewport(0, 0, width, height); 
glMatrixMode(GL_MODELVIEW); 
glPushMatrix(); 
// ... 

e il successivo dopo la resa effettiva:

// ... 
glPopMatrix(); 
glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0); 

Infine, ogni volta che lo schermo viene ridisegnato Io mappare la trama a un quad nella posizione appropriata sullo schermo, in questo modo:

float Vertices[] = { 
    -65.0f, -100.0f, .0f, 
    -65.0f, 100.0f, .0f, 
    -10.0f, -100.0f, .0f, 
    -10.0f, 100.0f, .0f}; 
float Texture[] = {.0f, .0f, 1.0f, .0f, .0f, 1.0f, 1.0f, 1.0f}; 

glEnable(GL_TEXTURE_2D); 
glEnableClientState(GL_VERTEX_ARRAY); 
glEnableClientState(GL_TEXTURE_COORD_ARRAY); 

glBindTexture(GL_TEXTURE_2D, wTexture); 
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 

glVertexPointer(3, GL_FLOAT, 0, Vertices); 
glTexCoordPointer(2, GL_FLOAT, 0, Texture); 
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 

glDisableClientState(GL_VERTEX_ARRAY); 
glDisableClientState(GL_TEXTURE_COORD_ARRAY); 
glDisable(GL_TEXTURE_2D); 

glBindTexture(GL_TEXTURE_2D, 0); 

Sui simulatori iPhone e iPad (4.2, 4.3), il codice funziona come previsto. Vedo la texture visualizzata dinamicamente nella rispettiva posizione, ovviamente con una rosa invece di uno sfondo trasparente a causa della mia dichiarazione di debug. Sul mio dispositivo iPad 4.2, tuttavia, viene eseguito il rendering solo del rettangolo rosa, non di quello che avrebbe dovuto essere disegnato durante il passaggio rendering-trama. Pertanto, la texture viene visualizzata correttamente sullo schermo, ma per qualche motivo, sul dispositivo il codice render-to-texture non riesce a rendere effettivamente nulla alla texture.

Suppongo che sto usando alcune funzionalità che non sono disponibili sul dispositivo, o faccio un'assunzione errata da qualche parte, ma non riesco a capire di cosa si tratta. Ho anche provato a eseguirlo tramite OpenGL ES Analyzer, ma non mi dà altro che alcuni suggerimenti di ottimizzazione delle prestazioni di base. Dove devo cercare il problema?

risposta

9

Stavo usando MSAA nel mio progetto e ho scoperto che il problema è scomparso quando l'ho disabilitato. Questo mi ha portato a scoprire this other question dove lo stesso problema è discusso (ma non risolto).

Il problema sembra essere che se il multicampionamento è abilitato per il framebuffer principale, tutti i FBO personalizzati devono utilizzare anche il multicampionamento. Non si può rendere ad un normale non multicampionato GL_TEXTURE_2D, e un multicampionato GL_TEXTURE_2D_MULTISAMPLE non è disponibile su OpenGL ES 2.

Al fine di risolvere il problema, ho modificato il mio codice render-to-texture allo stesso modo ho modificato il mio codice di rendering principale per abilitare il multicampionamento.Oltre ai tre oggetti buffer creati nel codice dalla questione, creo più tre per il rendering multi-campionato:

glGenFramebuffersOES(1, &wmBuffer); 
glGenRenderbuffersOES(1, &wmColor); 
glBindFramebufferOES(GL_FRAMEBUFFER_OES, wmBuffer); 
glBindRenderbufferOES(GL_RENDERBUFFER_OES, wmColor); 
glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER_OES, 4, GL_RGBA8_OES, width, height); 
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, wmColor); 
glGenRenderbuffersOES(1, &wmDepth); 
glBindRenderbufferOES(GL_RENDERBUFFER_OES, wmDepth); 
glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER_OES, 4, GL_DEPTH_COMPONENT16_OES, width, height); 
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, wmDepth); 

Prima di pronunciare alla texture, mi legano il nuovo buffer MSAA:

glBindFramebufferOES(GL_FRAMEBUFFER_OES, wmBuffer); 

Infine, dopo il rendering, risolvo il MSAA FBO nel FBO consistenza allo stesso modo che faccio per il mio principale framebuffer di rendering:

glBindFramebufferOES(GL_READ_FRAMEBUFFER_APPLE, wmBuffer); 
glBindFramebufferOES(GL_DRAW_FRAMEBUFFER_APPLE, wBuffer); 
glResolveMultisampleFramebufferAPPLE(); 
GLenum attachments[] = {GL_DEPTH_ATTACHMENT_OES, GL_COLOR_ATTACHMENT0_OES, GL_STENCIL_ATTACHMENT_OES}; 
glDiscardFramebufferEXT(GL_READ_FRAMEBUFFER_APPLE, 3, attachments); 
glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0); 

Le trame vengono ora renderizzate correttamente (e le prestazioni sono eccezionali!)

Problemi correlati