渲染静态和动态图形OpenGL

时间:2014-05-29 16:31:10

标签: opengl-es opengl-es-2.0 framebuffer

我正在使用OpenGL管道开发IOS游戏。我已经能够将我想要的图形渲染到屏幕上,但是,我打电话glDrawElements太多次了,并且最终会遇到一些关于遇到性能问题的担忧。我的游戏中有几个静态元素,不需要在每个渲染周期渲染。有没有办法可以将静态元素渲染到一个帧缓冲区,将动态元素渲染到另一个帧缓冲区?

这是我尝试过的代码:

static BOOL renderThisFrameBuffer = YES;
    if (renderThisFrameBuffer) {
        glBindFramebuffer(GL_FRAMEBUFFER, interFrameBuffer);
        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glEnable(GL_BLEND);
        glEnable(GL_DEPTH_TEST);

        // Set up projection matrix
        CC3GLMatrix *projection = [CC3GLMatrix matrix];
        float h = 4.0f * OpenGLView.frame.size.height / OpenGLView.frame.size.width;
        [projection populateFromFrustumLeft:-2 andRight:2 andBottom:-h/2 andTop:h/2 andNear:4 andFar:50];
        glUniformMatrix4fv(projectionUniform, 1, 0, projection.glMatrix);

        glViewport(0, 0, OpenGLView.frame.size.width, OpenGLView.frame.size.height);

        for (BoardSpace *boardSpace in spaceArray){
            [boardSpace drawWithMatrix:modelView];
        }

        [context presentRenderbuffer:GL_RENDERBUFFER];
        glBindFramebuffer(GL_FRAMEBUFFER, constFrameBuffer);
        renderThisFrameBuffer = false;
    }

在这种情况下,我之前创建了两个帧缓冲区:静态元素为interFrameBuffer,动态元素为constFrameBuffer。我错过了什么吗?

1 个答案:

答案 0 :(得分:2)

应该可以。最直接的方法是将静态元素渲染到FBO一次。然后在每次重绘时,将静态FBO的内容复制到默认的帧缓冲区,然后在其上绘制动态元素。

ES 2.0的功能集是一种支持此功能的边界线。例如,您没有glBlitFramebuffer(),这是将FBO内容复制到默认帧缓冲区的便捷方式。但是您可以使用简单的着色器程序进行复制,该程序通过顶点着色器中的坐标进行提供,并且仅在片段着色器中使用纹理样本操作。然后将渲染静态内容的纹理绑定到,并绘制一个大小为四的屏幕。

如果动态渲染需要静态渲染的深度缓冲区,则会变得更加棘手。例如,如果动态内容被静态内容遮挡,则会出现这种情况。在这种情况下,您还需要复制深度缓冲区。通过快速刷新我对规范的记忆,我没有看到任何可以在ES 2.0中实现这一点的东西。 glBlitFramebuffer()不在那里。看起来ES 2.0不支持深度纹理。如果你想去那里,你将进入ES 3.0领域。

有了这一切,你显然希望确保它真的有助于你的表现。复制帧缓冲区不是免费的。如果它比渲染静态元素便宜,它只会得到回报。在做出决定之前,两种方法的基准测试肯定是有条理的。