我想将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 quad渲染为tex2的FBO。但不知何故,我认为它还是天真的。那么实现这个的最有效方法是什么?
答案 0 :(得分:16)
如果您支持OpenGL 4.3,那么就可以直接glCopyImageSubData
来实现此目的:
glCopyImageSubData(tex1, GL_TEXTURE_2D, 0, 0, 0, 0,
tex2, GL_TEXTURE_2D, 0, 0, 0, 0,
width, height, 1);
当然这要求目标纹理已经分配了适当大小和格式的图像(使用简单的glTexImage2D(..., nullptr)
,或者如果你有GL 4则可能更好glTexStorage2D
。)< / p>
如果你没有,那么使用FBO将一个纹理渲染到另一个纹理可能仍然是最好的方法。最后,您甚至不需要渲染源纹理。您可以将两个纹理附加到FBO,然后使用glBlitFramebuffer
将一个颜色附件插入另一个颜色附件(自OpenGL 3后为核心,或者在2.x中使用GL_EXT_framebuffer_blit扩展,几乎在FBO首先出现的任何位置):
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保持活力可能是个好主意。同样,这也要求目标纹理图像预先具有适当的大小和格式。或者你也可以使用迈克尔的建议,即只将源纹理附加到FBO并在目标纹理中做一个好的旧glCopyTex(Sub)Image2D
。需要评估哪些表现更好(如果有的话)。
如果你甚至没有那个,那么你仍然可以使用你的方法来读取一个纹理并将数据写入另一个纹理。但是,不使用CPU内存作为临时缓冲区,而是使用pixel buffer object (PBO)(自OpenGL 2.1以来的核心)。您仍然会有一个额外的副本,但至少会有(或可能是)GPU-GPU副本。