为了提高我在 iPad 上的 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 上的A glFramebufferStatusOES
(当然是在它未绑定之前)在模拟器和设备上产生一个“帧缓冲区完成”返回值。请注意,我为纹理设置了粉红色的透明颜色,以确认纹理实际上已被渲染,而问题实际上只是纹理从未被绘制到。
每当需要重新绘制纹理时,我都会在渲染元素之前执行此操作:
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 Analyzer 运行它,但它只给了我一些基本的性能优化技巧。我需要在哪里寻找问题?