16

我想将texture1复制到texture2。最笨的方法是把tex1数据从GPU复制到CPU,然后再把CPU数据复制到GPU。愚蠢的代码如下:

float *data = new float[width*height*4];
glBindTexture(GL_TEXTURE_2D, tex1);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, data);
glBindTexture(GL_TEXTURE_2D, tex2]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, data);

据我所知,它必须存在一种支持将数据从 GPU tex 复制到 GPU tex 而不涉及 CPU 的方法。我考虑使用将 tex1 四边形渲染到 tex2 的 FBO。但不知何故,我认为这仍然是幼稚的。那么实现这一点的最有效方法是什么?

4

1 回答 1

21

如果您支持 OpenGL 4.3,则可以直接glCopyImageSubData用于此目的:

glCopyImageSubData(tex1, GL_TEXTURE_2D, 0, 0, 0, 0,
                   tex2, GL_TEXTURE_2D, 0, 0, 0, 0,
                   width, height, 1);

当然,这要求目标纹理已经分配了适当大小和格式的图像(使用简单的,或者如果你有 GL 4glTexImage2D(..., nullptr)可能会更好)。glTexStorage2D


如果你没有那个,那么使用 FBO 将一个纹理渲染到另一个纹理可能仍然是最好的方法。最后,您甚至不需要渲染源纹理。您可以将两个纹理附加到 FBO 并使用glBlitFramebuffer(自 OpenGL 3 以来的核心,或 2.x 中的 GL_EXT_framebuffer_blit 扩展,几乎任何首先出现 FBO 的地方)将一个颜色附件blit到另一个:

glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 
                       GL_TEXTURE_2D, tex1, 0);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, 
                       GL_TEXTURE_2D, tex2, 0);
glDrawBuffer(GL_COLOR_ATTACHMENT1);
glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, 
                  GL_COLOR_BUFFER_BIT, GL_NEAREST);

当然,如果你多次这样做,让这个 FBO 保持活力可能是个好主意。同样,这也要求目标纹理图像事先具有适当的大小和格式。或者您也可以使用Michael的建议,即仅将源纹理附加到 FBO 并glCopyTex(Sub)Image2D在目标纹理中做一个好的旧的。需要评估哪个表现更好(如果有的话)。


如果您甚至没有那个,那么您仍然可以使用读取一个纹理并将该数据写入另一个纹理的方法。但不要将 CPU 内存用作临时缓冲区,而是使用像素缓冲区对象 (PBO)(自 OpenGL 2.1 以来的核心)。您仍然会有一个额外的副本,但至少会(或可能是)一个 GPU-GPU 副本。

于 2013-04-19T08:55:07.183 回答