OpenGL帧缓冲性能问题

Posted

技术标签:

【中文标题】OpenGL帧缓冲性能问题【英文标题】:OpenGl framebuffer performance problems 【发布时间】:2014-01-31 21:42:03 【问题描述】:

我目前正在尝试为我用 JAVA 开发的游戏创建一个简单的光照引擎。我正在使用帧缓冲区对象将光源的图像绘制到环境颜色上,并将其与先前渲染的场景相结合以获得简单的照明。一切都很好,除了帧率减半,从稳定的 60 FPS 到波动的 30 FPS。

这是我目前的做法:

(这是在我的主显示循环中完成的)

        int[] params1 = new int[1];
        gl2.glGenTextures(1, params1, 0);
        int textureID = params1[0];
        gl2.glBindTexture(GL.GL_TEXTURE_2D, textureID);
        gl2.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST);
        gl2.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST);
        gl2.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA8, Game.RES_WIDTH, Game.RES_HEIGHT, 0, GL.GL_BGRA, GL.GL_UNSIGNED_BYTE, null);

        int[] params2 = new int[1];
        gl2.glGenFramebuffers(1, params2, 0);
        int frameBufferID = params2[0];
        gl2.glBindFramebuffer(GL2.GL_DRAW_FRAMEBUFFER, frameBufferID);
        gl2.glClear(0);
        gl2.glFramebufferTexture2D(GL2.GL_DRAW_FRAMEBUFFER, GL.GL_COLOR_ATTACHMENT0, GL.GL_TEXTURE_2D, textureID, 0);

        DrawUtils.fillRect(0, 0, Game.WIDTH, Game.HEIGHT, getAmbientLight()); 

        gl2.glBlendFunc(GL2.GL_SRC_ALPHA, GL2.GL_DST_ALPHA);    

        //Code for drawing the light sources here...

        gl2.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0);
        gl2.glBlendFunc(GL2.GL_DST_COLOR, GL2.GL_ONE_MINUS_SRC_ALPHA);

        gl2.glEnable(GL2.GL_TEXTURE_2D);
        gl2.glPushMatrix();
        gl2.glColor3f(1.0F, 1.0F, 1.0F);
        gl2.glBindTexture(GL2.GL_TEXTURE_2D, textureID);
        gl2.glBegin(GL2.GL_QUADS);
        gl2.glNormal3i(0, 0, 1);
        gl2.glTexCoord2i(0, 0);
        gl2.glVertex2i(0, 0);
        gl2.glTexCoord2i(1, 0);
        gl2.glVertex2i(0 + Game.WIDTH, 0);
        gl2.glTexCoord2i(1, 1);
        gl2.glVertex2i(Game.WIDTH, Game.HEIGHT);
        gl2.glTexCoord2i(0, 1);
        gl2.glVertex2i(0, Game.HEIGHT);
        gl2.glEnd();
        gl2.glPopMatrix();
        gl2.glDisable(GL2.GL_TEXTURE_2D);

        gl2.glBlendFunc(GL2.GL_SRC_ALPHA, GL2.GL_ONE_MINUS_SRC_ALPHA);

        gl2.glDeleteTextures(1, params1, 0);
        gl2.glDeleteFramebuffers(1, params2, 0);

【问题讨论】:

您应该分析您的代码以查看减速的位置。 我是gl2.glGenFramebuffers(1, params2, 0); 是否有可能提前生成您需要的帧缓冲区并在每次循环中重复使用它们? 坏消息是glGenFramebuffers (...) 实际上并没有做任何事情。它返回第一个未使用的名称并保留它,仅此而已。这意味着您用来确定瓶颈是此功能的任何技术都是错误的。 gl2.glBindFramebuffer (...) 很可能是您的实际瓶颈——这是唯一一个在 glGenFramebuffers (...) 附近具有任何可测量开销的 API 调用。这实际上会在您保留后创建 FBO,这可能会产生可观的开销。如果您的瓶颈合法地是glGenFramebuffers (...),那么 JOGL 做错了什么。 我很好奇,你为什么给glClear (...)一个位掩码0?你告诉它什么都不清除。虽然这不会设置任何错误位,因此不会产生错误,但它也是完全没有意义的。 【参考方案1】:

将帧缓冲区创建移出我的循环确实解决了问题:

public void init(GL2 gl2)

    int[] params1 = new int[1];
    gl2.glGenTextures(1, params1, 0);
    textureID = params1[0];
    gl2.glBindTexture(GL.GL_TEXTURE_2D, textureID);
    gl2.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST);
    gl2.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST);
    gl2.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA8, Game.RES_WIDTH, Game.RES_HEIGHT, 0, GL.GL_BGRA, GL.GL_UNSIGNED_BYTE, null);

    int[] params2 = new int[1];
    gl2.glGenFramebuffers(1, params2, 0);
    frameBufferID = params2[0];
    gl2.glBindFramebuffer(GL2.GL_DRAW_FRAMEBUFFER, frameBufferID);
    gl2.glFramebufferTexture2D(GL2.GL_DRAW_FRAMEBUFFER, GL.GL_COLOR_ATTACHMENT0, GL.GL_TEXTURE_2D, textureID, 0);

    gl2.glBindFramebuffer(GL2.GL_DRAW_FRAMEBUFFER, 0);

【讨论】:

以上是关于OpenGL帧缓冲性能问题的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL 的低性能水平

OpenGL 帧缓冲区缺失面

快速交换帧缓冲区 OpenGL

在 OpenGL ES 1.1 中使用顶点缓冲区对象绘图不起作用

关于 OpenGL 纹理、帧缓冲区和 UV 坐标的问题 [关闭]

在 OpenGL 中显示帧缓冲区