2011-09-06 46 views
9

Để cải thiện hiệu suất của ứng dụng OpenGL ES cho iPad, tôi đã lên kế hoạch để vẽ yếu tố nặng nhưng được cập nhật hiếm , vì vậy tôi chỉ có thể sử dụng kết cấu trừ khi phần tử phải được vẽ lại. Tuy nhiên, trong khi kết cấu được ánh xạ chính xác trên cả trình mô phỏng và thiết bị, chỉ trên trình mô phỏng là thứ gì đó thực sự được đưa vào kết cấu.Hiển thị kết cấu trên iOS OpenGL ES — hoạt động trên trình mô phỏng, nhưng không phải trên thiết bị

Sau đây là mã mà tôi đã thêm vào dự án. Trong khi thiết lập hiện trường, tôi có thể tạo các bộ đệm và kết cấu cần thiết:

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

Một glFramebufferStatusOES trên FBO mới (trước khi nó được cởi ra dĩ nhiên) mang lại một 'bộ đệm khung hoàn chỉnh' giá trị lợi nhuận trên cả hai trình giả lập và thiết bị. Lưu ý rằng tôi thiết lập màu sắc rõ ràng màu hồng cho kết cấu để xác nhận rằng kết cấu thực sự được hiển thị và vấn đề trên thực tế chỉ đơn giản là kết cấu không bao giờ được vẽ vào.

Bất cứ khi nào kết cấu cần được vẽ lại, tôi làm điều này trước khi render các yếu tố:

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

và sau đây sau khi dựng hình thực tế:

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

Cuối cùng, mỗi khi màn hình được vẽ lại Tôi lập bản đồ kết cấu với hình tứ giác ở vị trí thích hợp trên màn hình, như vậy:

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

Trên các trình mô phỏng iPhone và iPad (4.2, 4.3), mã hoạt động như mong đợi. Tôi thấy kết cấu động được hiển thị ở vị trí tương ứng, tất nhiên với một màu hồng thay vì nền trong suốt do tuyên bố gỡ lỗi của tôi. Trên thiết bị iPad 4.2 của tôi, tuy nhiên, chỉ có hình chữ nhật màu hồng được hiển thị, không phải những gì cần phải được rút ra trong nó trong bước render-to-texture. Do đó, kết cấu được hiển thị chính xác trên màn hình, nhưng vì lý do nào đó, trên thiết bị, mã render-to-texture không thực sự render bất cứ thứ gì lên texture.

Tôi cho rằng tôi đang sử dụng một số chức năng không khả dụng trên thiết bị hoặc thực hiện một giả định sai lầm ở đâu đó, nhưng tôi không thể hiểu được nó là gì. Tôi cũng đã thử chạy nó thông qua OpenGL ES Analyzer, nhưng nó mang lại cho tôi gì, nhưng một số mẹo tối ưu hóa hiệu suất cơ bản. Tôi cần tìm vấn đề ở đâu?

Trả lời

9

Tôi đã sử dụng MSAA trong dự án của mình và đã phát hiện ra rằng sự cố đã biến mất khi tôi vô hiệu hóa nó. Điều này đã dẫn tôi khám phá ra this other question trong đó cùng một vấn đề được thảo luận (nhưng không được giải quyết).

Vấn đề có vẻ là nếu multisampling được kích hoạt cho bộ đệm khung chính của bạn, tất cả FBO tùy chỉnh của bạn cũng phải sử dụng ghép nhiều lớp. Bạn không thể hiển thị với một số không bình thường không được ghép đôi là GL_TEXTURE_2D và một mẫu được lấy mẫu đa số GL_TEXTURE_2D_MULTISAMPLE không có sẵn trên OpenGL ES 2.

Để sửa lỗi mã kết xuất giống như cách tôi đã sửa đổi mã hiển thị chính của tôi để cho phép ghép nhiều lớp.Ngoài ba đối tượng đệm tạo ra trong mã từ câu hỏi, tôi có thể tạo ba hơn đối với đa mẫu vẽ:

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

Trước khi hiển thị ở kết cấu, tôi gắn bộ đệm MSAA mới:

glBindFramebufferOES(GL_FRAMEBUFFER_OES, wmBuffer); 

Cuối cùng, sau khi render, tôi giải quyết MSAA FBO vào FBO kết cấu giống như cách tôi làm cho bộ đệm khung vẽ chính của tôi:

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

Kết cấu hiện được hiển thị chính xác (và hiệu suất là tuyệt vời!)

Các vấn đề liên quan