我使用2D纹理数组来存储一些数据。由于我经常想要绑定此2D纹理数组的单个图层,因此我为每个图层创建了单独的 GL_TEXTURE_2D 纹理视图:
for(int l(0); l < m_layers; l++)
{
QOpenGLTexture * view_texture = m_texture.createTextureView(QOpenGLTexture::Target::Target2D,
m_texture_format,
0,0,
l,l);
view_texture->setMinMagFilters(QOpenGLTexture::Filter::Linear, QOpenGLTexture::Filter::Linear);
view_texture->setWrapMode(QOpenGLTexture::WrapMode::MirroredRepeat);
assert(view_texture != 0);
m_texture_views.push_back(view_texture);
}
这些2D TextureViews工作正常。但是,如果我想使用该纹理视图从GPU端检索2D纹理数据,它就无法工作。
换句话说,以下复制没有数据(但不会引发GL错误):
glGetTexImage(GL_TEXTURE_2D, 0, m_pixel_format, m_pixel_type, (GLvoid*) m_raw_data[layer] )
但是,检索整个 GL_TEXTURE_2D_ARRAY 确实有效:
glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, m_pixel_format, m_pixel_type, (GLvoid*) data );
如果我只需修改单个图层的数据,那么当我需要复制2D纹理数组的所有图层时,显然会出现性能损失。
有没有办法复制GPU-&gt; CPU只有一层 GL_TEXTURE_2D_ARRAY ?我知道存在相反的情况(即CPU-> GPU),所以如果没有,我会感到惊讶。
答案 0 :(得分:4)
您似乎找到了使用OpenGL 4.5中的glGetTexSubImage()
的解决方案。还有一个适用于OpenGL 3.2或更高版本的简单解决方案。
您可以将纹理图层设置为FBO附件,然后使用glReadPixels()
:
GLuint fboId = 0;
glGenFramebuffers(1, &fboId);
glBindFramebuffer(GL_READ_FRAMEBUFFER, fboId);
glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
textureId, 0, layer);
glReadPixels(...);
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
答案 1 :(得分:3)
您使用的是什么版本的GL?
你可能不会喜欢这个,但...... GL 4.5引入glGetTextureSubImage (...)
来做你想要的。对于这么简单的事情,这是一个非常大的版本要求;它也可以在extension form中使用,但该扩展也是相对较新的。
此功能没有特殊的硬件要求,但它需要一个非常新的驱动程序。
然而,我不会绝望。
您可以将整个纹理数组复制到PBO中,然后使用缓冲区对象API(例如 glGetBufferSubData (...)
)读回该PBO的子矩形。这需要GPU端额外的内存,但允许您传输这个2D阵列的单个片段。