【问题标题】:How to copy texture1 to texture2 efficiently?如何有效地将texture1复制到texture2?
【发布时间】:2013-04-12 14:12:59
【问题描述】:

我想将纹理 1 复制到纹理 2。 最笨的方法是把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。但不知何故,我认为这仍然是幼稚的。那么实现这一点的最有效方法是什么?

【问题讨论】:

  • glCopyTexImage2D 从颜色缓冲区复制到纹理。我认为它应该有一种方法可以避免渲染到颜色缓冲区或帧缓冲区。
  • FBO 中的颜色缓冲区也可以是纹理。
  • 你的意思是使用FBO renderingToTexture?我知道这可行。我认为应该有更好的方法。就像在 CUDA 中一样,我们可以使用 cudamemcpy(..,cudaMemcpyDeviceToDevice)
  • 由于 CUDA ist NV 特定并且基本上会做同样的事情,我认为 FBO 使用更好是可能的。

标签: opengl textures


【解决方案1】:

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


如果您没有,那么使用 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 内存作为临时缓冲区,而是使用 pixel buffer object (PBO)(自 OpenGL 2.1 以来的核心)。您仍然会有额外的副本,但至少会(或可能是)GPU-GPU 副本。

【讨论】:

  • 你确定 4.0 , 4.1 ,4.2 也没有这个功能吗?
  • @MichaelIV 它最有可能通过向后移植的核心扩展(但它只是 4.3 中的核心)可用于任何 4.x,但话又说回来,在特定的 4.x 之间进行选择通常只是无论如何,一个驱动程序问题。如果你有 4.1,那么在安装最新的驱动程序后你很可能有 4.3(假设你首先使用的是具有合理驱动程序的硬件,比如 xXxxxx,而不是像 XXX 垃圾这样的东西;))。
  • @Christian Rau。太好了!我想你解释了一切。此外,我想问:1)我需要创建 GL4 或 GL3 上下文来使用前两种方法吗?或者我可以简单地在我现有的代码中使用这些函数? 2).我的显卡支持OpenGL3.3。那么 glCopyImageSubData 无论如何都不适合我吗?我找到了函数CopyImageSubDataNV。这适用于我的卡吗?
  • @rtrobin glCopySubImageData 很可能不可用。它是自 GL 4.3 以来的唯一核心,我认为即使作为扩展,它也只能在 4 级硬件上使用。除此之外,如果您像往常一样创建 GL 上下文,您将获得显卡 驱动程序支持的最高版本。您不必显式请求 GL 3.3 上下文,仅当您需要核心上下文时才需要(没有弃用的向后功能,但上述功能均未弃用)。因此,如果您获得了最新的驱动程序,您至少可以使用第二种方法。
  • @rtrobin 但是你也可以看看你的实现是否支持GL_ARB_copy_image extension。从技术上讲,它只需要 GL 1.1,但实际上您至少需要 CUDA 硬件,因此它甚至可能在 OpenGL 3 硬件上得到支持。
猜你喜欢
  • 2010-09-09
  • 2021-04-23
  • 2020-05-16
  • 2011-05-27
  • 1970-01-01
  • 2019-01-10
  • 1970-01-01
  • 2021-09-12
  • 1970-01-01
相关资源
最近更新 更多