如何种植GL_TEXTURE_2D_ARRAY?

How to grow a GL_TEXTURE_2D_ARRAY?

我创建了这样的二维纹理数组

glTexImage3D(GL_TEXTURE_2D_ARRAY,
             0,                // No mipmaps
             GL_RGBA8,         // Internal format
             width, height, 100, // width,height,layer count
             0,                // border?
             GL_RGBA,         // format
             GL_UNSIGNED_BYTE, // type
             0);               // pointer to data

例如,如何将其大小从 100 增加到 200?我想我必须创建一个新的 2d 数组,大小为 200,然后用 glCopyTexSubImage3D over?

复制图像
glBindTexture(GL_TEXTURE_2D_ARRAY, texture_id);
glCopyTexSubImage3D(GL_TEXTURE_2D_ARRAY,
                         0,
                         0, 0, 0,
                         0, 0,
                         width, height
                         );
glDeleteTextures(1, &texture_id);

GLuint new_tex_id;
glGenTextures(1, &new_tex_id);
glBindTexture(GL_TEXTURE_2D_ARRAY, new_tex_id);

glTexImage3D(GL_TEXTURE_2D_ARRAY,
             0,                
             GL_RGBA8,         
             width, height, 200, 
             0,                
             GL_RGBA,         
             GL_UNSIGNED_BYTE, 
             0);               

//How do I get the data in `GL_READ_BUFFER` into my newly bound texture? 

texture_id = new_tex_id;

但是我实际上如何从 GL_READ_BUFFER 中获取数据?

glCopyTexSubImage 从帧缓冲区复制数据,而不是从纹理。这就是为什么它不需要两个纹理对象来复制。

从一个纹理复制到另一个纹理需要 glCopyImageSubData。这是来自 ARB_copy_image 的 OpenGL 4.3 函数。在NV_copy_image中也可以找到类似的功能,可能会得到更广泛的支持。

顺便说一句,您通常应该完全避免执行此操作。如果你需要一个 200 元素数组纹理,你应该在第一时间分配它。

@NicolBolas 指出的 glCopyImageSubData() 函数是最简单的解决方案,如果您可以接受 OpenGL 4.3 或更高版本。

您可以使用 glCopyTexSubImage3D() 来达到这个目的。但是由于此函数的源是当前读取的帧缓冲区,因此您需要将原始纹理绑定为帧缓冲区附件。代码大致如下所示:

GLuint fbo = 0;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);

glBindTexture(GL_TEXTURE_2D_ARRAY, new_tex_id);

for (int layer = 0; layer < 100; ++layer) {
    glFramebufferTextureLayer(GL_READ_FRAMEBUFFER,
        GL_COLOR_ATTACHMENT0, tex_id, 0, layer);
    glCopyTexSubImage3D(GL_TEXTURE_2D_ARRAY,
        0, 0, 0, layer, 0, 0, width, height);
}

您也可以使用 glBlitFramebuffer() 代替:

GLuint fbos[2] = {0, 0};
glGenFramebuffers(2, fbos);
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbos[0]);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[1]);

for (int layer = 0; layer < 100; ++layer) {
    glFramebufferTextureLayer(GL_READ_FRAMEBUFFER,
        GL_COLOR_ATTACHMENT0, tex_id, 0, layer);
    glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER,
        GL_COLOR_ATTACHMENT0, new_tex_id, 0, layer);
    glBlitFramebuffer(
        0, 0, width, height, 0, 0, width, height,
        GL_COLOR_BUFFER_BIT, GL_NEAREST);
}

这两个选项应该差不多。我可能会选择 glBlitFramebuffer() 因为它是一个较新的函数(在 3.0 中引入),而且它可能更常用。所以它可能会更优化。但是,如果这在您的应用程序中对性能至关重要,您应该同时尝试并比较。