2011-09-06 12 views
9

Para mejorar el rendimiento de mi aplicación OpenGL ES para el iPad, estaba planeando dibujar un elemento raramente actualizado pero muy pesado en una textura , entonces puedo usar la textura a menos que el elemento tenga que volver a dibujarse. Sin embargo, aunque la textura está asignada correctamente tanto en el simulador como en el dispositivo, solo en el simulador se representa algo realmente en la textura.Rendering a la textura en iOS OpenGL ES-funciona en el simulador, pero no en el dispositivo

El siguiente es el código que agregué al proyecto. Si bien la creación de la escena, puedo crear los tampones y la textura necesaria:

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); 

Un glFramebufferStatusOES en el nuevo FBO (antes de que no está consolidado, por supuesto) se obtiene un valor de retorno 'framebuffer completa' tanto en el simulador y el dispositivo. Tenga en cuenta que establezco el color rosa claro para la textura a fin de confirmar que la textura realmente se representa, y el problema es, de hecho, simplemente que la textura nunca se dibuja.

Siempre que la textura tiene que ser redibujado, hago esto antes de representar el elemento:

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

y la siguiente después de la representación real:

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

Por último, cada vez que la pantalla se vuelve a dibujar Asigné la textura a un cuadrángulo en la posición adecuada en la pantalla, así:

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); 

En los simuladores de iPhone e iPad (4.2, 4.3), el código funciona como se esperaba. Veo la textura presentada de forma dinámica en la posición correspondiente, por supuesto con un fondo de color rosa en lugar de transparente debido a mi declaración de depuración. En mi dispositivo iPad 4.2, sin embargo, solo se representa el rectángulo rosa, no lo que debería haberse dibujado en él durante el paso de renderizar a textura. Por lo tanto, la textura se representa correctamente en la pantalla, pero por alguna razón, en el dispositivo, el código de renderizar a textura no puede representar nada en la textura.

Supongo que estoy usando alguna funcionalidad que no está disponible en el dispositivo, o hago una suposición errónea en alguna parte, pero no puedo entender cuál es. También intenté ejecutarlo a través del OpenGL ES Analyzer, pero no me brinda más que algunos consejos básicos de optimización del rendimiento. ¿Dónde debo buscar el problema?

Respuesta

9

Estaba usando MSAA en mi proyecto, y descubrí que el problema desapareció cuando lo desactivé. Esto me ha llevado a descubrir this other question donde se discute el mismo problema (pero no se resuelve).

El problema parece ser que si la multimuestreo está habilitada para su framebuffer principal, todas sus FBO personalizadas también deben usar multisampling. No se puede renderizar a una normal no multimuestreado GL_TEXTURE_2D, y una multimuestreado GL_TEXTURE_2D_MULTISAMPLE no está disponible en OpenGL ES 2.

Con el fin de solucionar el problema, he modificado mi código-render-a la textura de la misma manera que he modificado mi código de renderizado principal para habilitar la multimuestreo.Además de los tres objetos de amortiguamiento creados en el código de la pregunta, crear tres más por el multi-muestreados renderizado:

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); 

Antes de emitir a la textura, Ato el nuevo buffer MSAA:

glBindFramebufferOES(GL_FRAMEBUFFER_OES, wmBuffer); 

Finalmente, después de rendir, puedo solucionar el OBF MSAA en el FBO textura de la misma manera que lo hago para mi uso de este dispositivo principal de renderizado:

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); 

Las texturas ahora se representan correctamente (y el rendimiento es excelente)

Cuestiones relacionadas