OpenGL glReadPixels性能

时间:2015-09-30 03:59:43

标签: opengl glreadpixels

我正在尝试为HDR色调映射实现自动曝光,我正在努力降低查找场景平均亮度的成本,而我似乎已经点击hbGciOi.eyJmdWWxsIiwiRGJn...的阻塞点。这是我的设置:

1:我创建了一个缩减采样的FBO,以便在仅使用glReadPixels值和glReadPixels格式使用GL_RED时降低阅读成本。

GL_BYTE

2:设置ByteBuffers并读取FBO纹理的纹理。

private void CreateDownSampleExposure() {
        DownFrameBuffer = glGenFramebuffers();
        DownTexture = GL11.glGenTextures();
        glBindFramebuffer(GL_FRAMEBUFFER, DownFrameBuffer);
        GL11.glBindTexture(GL11.GL_TEXTURE_2D, DownTexture);
        GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RED, 1600/8, 1200/8,
                0, GL11.GL_RED, GL11.GL_BYTE, (ByteBuffer) null);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                GL11.GL_TEXTURE_2D, DownTexture, 0);
        if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
            System.err.println("error");
        } else {
            System.err.println("success");
        }
        GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
        glBindFramebuffer(GL_FRAMEBUFFER, 0);

    }

问题是,我可以将我的FBO纹理缩减100倍,因此我的Setup(){ byte[] testByte = new byte[1600/8*1000/8]; ByteBuffer testByteBuffer = BufferUtils.createByteBuffer(testByte.length); testByteBuffer.put(testByte); testByteBuffer.flip(); } MainLoop(){ //Render scene and store result into downSampledFBO texture GL11.glBindTexture(GL11.GL_TEXTURE_2D, DeferredFBO.getDownTexture()); //GL11.glGetTexImage(GL11.GL_TEXTURE_2D, 0, GL11.GL_RED, GL11.GL_BYTE, //testByteBuffer); <- This is slower than readPixels. GL11.glReadPixels(0, 0, DisplayManager.Width/8, DisplayManager.Height/8, GL11.GL_RED, GL11.GL_BYTE, testByteBuffer); int x = 0; for(int i = 0; i <testByteBuffer.capacity(); i++){ x+= testByteBuffer.get(i); } System.out.println(x); <-Print out accumulated value of brightness. } //Adjust exposure depending on brightness. 只读取16x10像素,并且几乎没有性能增益。没有下采样有很大的性能提升,但是一旦我将宽度和高度除以8,它似乎就会下降。似乎只是调用这个函数就有这么大的开销。在调用glReadPixels时,我有什么不正确或不考虑的事情吗?

1 个答案:

答案 0 :(得分:2)

glReadPixels很慢,因为CPU必须等到GPU完成所有渲染之后才能给你结果。可怕的同步点。

使glReadPixels快速运行的一种方法是使用某种双/三缓冲方案,这样你只需要在你期望GPU已经完成的渲染到纹理上调用glReadPixels。只有在接收到glReadPixels结果之前等待几帧才能在您的应用程序中接受时,这才可行。例如,在视频游戏中,延迟可以证明是模拟瞳孔对光照条件变化的响应时间。

但是,对于您的特定色调映射示例,可能您只想计算平均亮度,以便将该信息反馈回GPU以进行另一次渲染过程。而不是glReadPixels,通过使用线性过滤(盒式过滤器)将图像复制到连续半尺寸的渲染目标来计算平均值,直到您降低到1x1目标。

1x1目标现在是包含平均亮度的纹理,可以在色调映射渲染过程中使用该纹理。没有同步点。