如何生长GL_TEXTURE_2D_ARRAY

How to grow a GL_TEXTURE_2D_ARRAY?

本文关键字:TEXTURE 2D ARRAY GL 何生长 生长      更新时间:2023-10-16

我已经创建了像这个一样的2d纹理阵列

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?我想我必须创建一个大小为200的新2d阵列,并用glCopyTexSubImage3D复制图像?

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。这是一个OpenGL 4.3函数,来自ARB_copy_image。类似的函数也可以在NV_copy_image中找到,它可能得到更广泛的支持。

顺便说一句,你通常应该避免做这个操作。如果您需要一个200元素的数组纹理,您应该在第一次分配它。

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

您可以将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中引入),而且它可能更常用。因此,它可能会更加优化。但是,如果这对您的应用程序的性能至关重要,您应该同时尝试这两种方法,并进行比较。