如何在同时运行多个OpenGL进程时防止FBO渲染损坏?

时间:2012-09-13 12:57:26

标签: c++ windows opengl

我需要能够使用OpenGL同时使用多个进程进行渲染。

我正在使用FBO渲染到纹理中。我通过glGetTexImage()在一个进程(平铺渲染)中多次读取像素。

然后我启动了多个同时运行的程序,并注意到它有时会起作用,有时则不行。有时整个图像被破坏(仅重复一个图块),有时只有一小部分被破坏。我之前也注意到由于某种原因我无法使用4096x4096大小的FBO纹理,并且该纹理大小的错误与此“多个进程一次”平铺错误相同,所以我认为它可能与程序试图获得尚未完全渲染的纹理?我还注意到我使用的纹理越小,我可以同时运行的进程越多。我认为我的GFX卡内存是256 MB。但即使有8个1024x1024大小纹理的进程,它最坏的时候只使用33 MB的内存,所以它不能成为我的GFX卡内存限制。

平铺错误看起来好像没有获得新的平铺像素数据,因此它再次使用旧的缓冲区。

如何防止渲染损坏?

这是我的渲染代码结构:

for(y...){
    for(x...){
        // set viewport & translatef

        glBindFramebuffer(GL_FRAMEBUFFER, fboId);
        // glclear()
        render_tile();
        glFlush();
        glBindFramebuffer(GL_FRAMEBUFFER, 0);

        glBindTexture(GL_TEXTURE_2D, textureId);
        glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels);
        glBindTexture(GL_TEXTURE_2D, 0);
        copy_tile_pixels_to_output_image();
    }
}

这是FBO初始化(仅显示与opengl相关的命令):

// texture:
glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_2D, textureId);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glBindTexture(GL_TEXTURE_2D, 0);

// FBO:
glGenFramebuffers(1, &fboId);
glBindFramebuffer(GL_FRAMEBUFFER, fboId);

glGenRenderbuffers(1, &rboId);
glBindRenderbuffer(GL_RENDERBUFFER, rboId);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, TEXTURE_WIDTH, TEXTURE_HEIGHT);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboId);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rboId);

checkFramebufferStatus(); // will exit if errors found. none found, however.

glBindFramebuffer(GL_FRAMEBUFFER, 0);

编辑:,正如datenwolf注意到的那样,使用glReadPixels()可以解决问题。但是我还不确定为什么,所以最好知道发生什么事情,以确保它在将来无论如何都不会出现这样的错误!

1 个答案:

答案 0 :(得分:0)

FBO本身只是一个没有自己的支持图像存储的抽象对象。基本上,FBO本身只包含插槽,您可以插入图像接收器和源。纹理可以这样作用,但也有渲染缓冲区,它们具有相同的用途,但不能用作纹理样本源

您可以使用glReadPixels直接从绑定的FBO读回。