如果您支持 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 副本。