2011-09-06 33 views
9

为了提高我的OpenGL ES应用程序在iPad上的性能,我打算绘制一个很少更新但重渲染的元素到纹理,所以我可以使用纹理,除非元素必须重绘。然而,虽然纹理在模拟器和设备上都能正确映射,但只有在模拟器上才会真正渲染到纹理中。在iOS上渲染纹理OpenGL ES-在模拟器上工作,但不在设备上

以下是我添加到项目中的代码。在设置的场景,我创建了缓冲和所需的质地:

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

在新的FBO(之前,它是未绑定的,当然)在glFramebufferStatusOES得到双方的模拟器“的framebuffer完整”返回值和设备。请注意,我为纹理设置了粉红色的清晰颜色,以确认纹理实际呈现,问题实际上仅仅是纹理从未被绘制。

每当质地需要重新绘制,我渲染元素之前做到这一点:

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

和实际渲染后如下:

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

最后,每次屏幕重绘我将纹理映射到屏幕上适当位置的四边形,如下所示:

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

在iPhone和iPad模拟器(4.2,4.3)上,代码按预期工作。由于我的调试语句,我看到动态渲染的纹理显示在相应的位置,当然是用粉色而不是透明背景。然而,在我的iPad 4.2设备上,只渲染了粉红色的矩形,而不是渲染到纹理步骤中应该绘制的东西。因此,纹理正确地呈现在屏幕上,但由于某种原因,在设备上,渲染到纹理代码无法实际渲染任何纹理。

我想我正在使用一些设备上不可用的功能,或者在某处作出错误的假设,但我无法弄清楚它是什么。我也尝试通过OpenGL ES分析器来运行它,但它只给我一些基本的性能优化提示。我需要在哪里寻找问题?

回答

9

我在我的项目中使用MSAA,并发现当我禁用它时问题消失。这导致我发现this other question讨论了相同的问题(但未解决)。

问题似乎是,如果为您的主帧缓冲器启用了多重采样,则您所有的自定义FBO也必须使用多重采样。你无法呈现正常的非多重采样GL_TEXTURE_2D,以及多采样GL_TEXTURE_2D_MULTISAMPLE不提供OpenGL ES的2

为了解决这个问题,我修改了渲染到纹理的代码,我修改了相同的方式我的主要渲染代码来启用多重采样。除了从问题的代码创建的三个缓冲区对象,我创建三个多为多重采样渲染:

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

渲染到纹理之前,我绑定新的MSAA缓存:

glBindFramebufferOES(GL_FRAMEBUFFER_OES, wmBuffer); 

最后,渲染后,我解决MSAA FBO到纹理FBO以同样的方式我为我的主渲染帧缓冲区做:

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

纹理现在渲染正确(并且性能很好!)

相关问题