2011-09-06 15 views
9

Aby poprawić wydajność mojej aplikacji OpenGL ES dla iPada, planowałem narysować element rzadko aktualizowany, ale z zachowaniem ciągłości renderowania, do tekstury , więc mogę po prostu użyć tekstury, chyba że element musi zostać przerysowany. Jednakże, podczas gdy tekstura jest poprawnie odwzorowana zarówno na symulatorze, jak i na urządzeniu, tylko na symulatorze jest coś faktycznie renderowanego do tekstury.Renderowanie tekstur na iOS OpenGL ES-działa na symulatorze, ale nie na urządzeniu

Poniżej znajduje się kod dodany do projektu. Podczas konfigurowania scenę, tworzę bufory i tekstura potrzebne:

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

glFramebufferStatusOES na nowym FBO (Przed niezwiązany oczywiście) daje się „bufora ramki Complete” zwracanej wartości zarówno na symulatorze i urządzenie. Zwróć uwagę, że ustawiam różową jasną barwę dla tekstury, aby potwierdzić, że tekstura jest faktycznie renderowana, a problem polega po prostu na tym, że tekstura nigdy nie jest wciągnięta.

Gdy faktura musi być odnawiany, robię to przed renderowania elementu:

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

i następujący po faktycznym renderowania:

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

Wreszcie, za każdym razem, ekran jest odświeżana Mapuję teksturę na kwadrat w odpowiedniej pozycji na ekranie, tak jak poniżej:

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

Na symulatorze iPhone'a i iPada (4.2, 4.3) kod działa zgodnie z oczekiwaniami. Widzę dynamicznie renderowaną teksturę wyświetlaną w odpowiedniej pozycji, oczywiście z różowym zamiast przezroczystym tłem z powodu mojego stwierdzenia debugowania. Jednak na moim urządzeniu iPad 4.2 renderowany jest tylko różowy prostokąt, a nie to, co powinno zostać wciągnięte podczas etapu renderowania do tekstury. W ten sposób tekstura jest poprawnie wyświetlana na ekranie, ale z jakiegoś powodu na kodzie renderowania do tekstury nie renderuje niczego do tekstury.

Przypuszczam, że używam niektórych funkcji, które nie są dostępne na urządzeniu, lub gdzieś zakładam błędne założenie, ale nie wiem, co to jest. Próbowałem także uruchomić go za pomocą OpenGL ES Analyzer, ale daje mi to tylko kilka podstawowych wskazówek dotyczących optymalizacji wydajności. Gdzie muszę szukać problemu?

Odpowiedz

9

Użyłem MSAA w moim projekcie i odkryłem, że problem zniknął, gdy go wyłączyłem. To doprowadziło mnie do odkrycia this other question, gdzie ten sam problem jest omawiany (ale nie rozwiązany).

Problem polega na tym, że jeśli włączone jest multisampling dla głównego bufora ramki, wszystkie niestandardowe serwery FBO muszą również wykorzystywać multisampling. Nie można renderować do normalnego non-multisampled GL_TEXTURE_2D, a multisampled GL_TEXTURE_2D_MULTISAMPLE nie jest dostępny na OpenGL ES 2.

Aby rozwiązać ten problem, że mój zmodyfikowany kod do renderowania tekstur w ten sam sposób ja zmodyfikowanego mój główny kod renderujący, aby umożliwić multisampling.Oprócz trzech obiektów buforowanych utworzonych w kod z pytaniem utworzyć kolejne trzy do wielu próbkowany utylizacyjnej:

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

Przed topieniem teksturze, wiążę nowy bufor MSAA:

glBindFramebufferOES(GL_FRAMEBUFFER_OES, wmBuffer); 

Wreszcie, po renderingu rozwiązać MSAA FBO do tekstury FBO tak samo robię dla mojego głównego bufora ramki renderowania:

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

Tekstury są teraz renderowane poprawnie (a wydajność jest świetna!)

Powiązane problemy