Да, glReadPixels
может читать другие фрагменты из 3D-текстуры. Нужно просто использовать glFramebufferTextureLayer
, чтобы прикрепить правильный текущий срез к FBO - вместо того, чтобы прикреплять полную трехмерную текстуру в качестве цветовой привязки. Вот код замены для glGetTexImage
(специальный FBO для этого, fboForTextureSaving
, должен быть сгенерирован заранее):
GLint origReadFramebuffer=0, origDrawFramebuffer=0;
gl.glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &origReadFramebuffer);
gl.glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &origDrawFramebuffer);
gl.glBindFramebuffer(GL_FRAMEBUFFER, fboForTextureSaving);
for(int layer=0; layer<depth; ++layer)
{
gl.glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
texture, 0, layer);
checkFramebufferStatus("framebuffer for saving textures");
gl.glReadPixels(0,0,w,h,GL_RGBA,GL_FLOAT, subpixels+layer*w*h*4);
}
gl.glBindFramebuffer(GL_READ_FRAMEBUFFER, origReadFramebuffer);
gl.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, origDrawFramebuffer);
В любом случае, это не является долгосрочным решением проблемы , Первой причиной ошибок GL_OUT_OF_MEMORY
с большими текстурами на самом деле является нехватка ОЗУ или VRAM. Это тоньше: каждая текстура, размещенная на GPU, отображается в адресное пространство процесса (по крайней мере, в Linux / nvidia
). Таким образом, если ваш процесс не malloc
хотя бы половину доступной ему оперативной памяти, его адресное пространство может уже использоваться этими большими отображениями. Добавьте к этому немного фрагментации памяти, и вы получите либо GL_OUT_OF_MEMORY
, либо malloc
сбой, либо std::bad_alloc
где-то даже раньше, чем ожидалось.
Надлежащее долгосрочное решение - принять 64 и скомпилируйте ваше приложение как 64-битный код. Это то, что я в итоге сделал, избавившись от всего этого послойного кладжа и немного упростив код.