如何种植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 中引入),而且它可能更常用。所以它可能会更优化。但是,如果这在您的应用程序中对性能至关重要,您应该同时尝试并比较。
我创建了这样的二维纹理数组
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 中引入),而且它可能更常用。所以它可能会更优化。但是,如果这在您的应用程序中对性能至关重要,您应该同时尝试并比较。