在OpenGL中,是否可以从多个Texture2D对象创建一个Texture2D_Array?

3
关于我的意图:
我有一个图像堆栈,由于几个原因,我需要它们分离成单独的2D纹理。然后为了一些组合显示,我需要将其中5-10个融合在一个显示中(非常适合Texture2d_Array)。我的想法是将已上传的2D纹理形成Texture2d数组。这是OpenGL提供给我的函数可以实现的吗?
备注:我想避免重新加载图像数据,并且出于效率的原因,已经创建的mip-maps非常有用,应保留它们。因此,“从Tex2d获取数据并创建新的Tex2Darray层”的操作是愚蠢的。
如果失败了,我的备选方案是在我的Shader中拥有约10个采样器,并在显示前将它们相加/平均。
2个回答

3

任何事情都有可能发生!嗯,几乎任何事情...

根据您可用的OpenGL版本,您可以考虑几个选项。如果您确实需要复制数据,那么这是一些选项。当然,远远最好的选择是首先将纹理数据加载到数组纹理中,并避免额外的复制。

glCopyImageSubData()

glCopyImageSubData()非常直接地匹配了您想要的功能。唯一的缺点是它只在OpenGL 4.3及更高版本中可用。

glCopyTexImage2D()

我提到这个只是为了完整起见,以防有人看这个答案时略微不同的用例。glCopyTexImage2D()通常可用于通过将源纹理设置为FBO附件来复制纹理数据。

但事实证明,它不支持GL_TEXTURE_2D_ARRAY,因此无法用于从普通纹理复制到数组纹理。另一个方向将起作用。

glBlitFramebuffer()

glBlitFramebuffer()在OpenGL 3.0及更高版本中可用,可用于复制几乎任何类型的帧缓冲/纹理数据。

要从纹理复制到纹理,您需要创建两个FBO。您将其中一个绑定为GL_READ_FRAMEBUFFER,并将源纹理附加到其中。您将第二个绑定为GL_DRAW_FRAMEBUFFER,并将目标纹理附加到其中。然后调用glBlitFramebuffer()


谢谢你的回答。虽然不确定我能从中借鉴什么,但也许我可以创建不完整的Texture2D数组,其中只有50个图层中的0..4被设置为有效数据。这是可能的吗?它会消耗内存吗(因为这涉及DICOM,所以图像大小达到2k²甚至更大)? - Robetto

1

您可以使用以下两种技术的组合来绕过每个纹理都在单独的2D纹理中的限制:

glTextureView()

创建一个单一的纹理数组,然后使用glTextureView()(OpenGL 4.3+中的核心功能)创建单独的2D纹理,这些纹理的行为与您当前存在的纹理完全相同。与Reto Koradi所概述的函数不同之处在于,纹理视图不会在GPU上复制内存,这可能根据您的需求更有效率。

但是,您不能使用此函数将多个现有的2D纹理映射到新的2D数组中,正如您请求的那样。原因很简单,在OpenGL中没有足够的控制GPU内存映射,尽管至少在某些情况下(假设每个切片的大小可被GPU的内存控制器的页面大小整除),这是可能的。

纹理集

你不一定需要为每个特殊用例创建一个精确的2D纹理切片集合的新纹理数组,而是将包含所有纹理的大型纹理数组绑定到单个(或多个)采样器,并与选择所需纹理的切片索引数组一起传递到着色器。 如果你愿意/能够更改着色器源代码,则显然只有这个选项是可行的。

谢谢。所以我读到:nTex2D -> Tex2D-Array 不可能,但是 / Tex2D-Array -> nTex2D 是可能的。!? 反过来会更好,因为我的瓶颈(我应该写一下)是内存。我的纹理是2k²或其他5k*4k的Dicom图像,加载50个2k²的图像肯定会使显卡崩溃。所以我正在尝试找到在内存中只加载最少数量的纹理的可行方法。 - Robetto
1
如果所有纹理的总内存大小是一个问题,您可以检查目标平台上是否可用GL_ARB_sparse_texture。如果是这样,您可以选择从视频内存中删除任何纹理切片甚至mipmap级别,并在系统内存中保留备份。这样,您就可以完全控制纹理流媒体策略,以在需要时使数据可用。请注意,从纯内存大小的角度来看,纹理数组不提供任何好处,因此同样适用于简单的2D纹理列表。 - Stacker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接