您是否只是复制并粘贴了该代码(以及该代码)?那么它失败的原因是:
- 您要从 OpenGL 中读取像素的缓冲区对象不存在;因此映射它会失败,这意味着你将 OpenEXR 指向一个空指针
- 上面的代码中根本没有单一的错误条件检查。
改为这样做:
首先是一个帮助器,用于清理 OpenGL 错误堆栈(可能会累积多个错误条件):
int check_gl_errors()
{
int errors = 0;
while( GL_NO_ERROR != glGetError() ) { errors++; }
return errors;
}
那么这个
int const width = 512;
int const height = 512;
size_t const sizeof_half_float = 2;
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboId);
glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pboId);
glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB,
width * height * sizeof_half_float,
NULL,
GL_STATIC_READ_ARB);
if( !check_gl_errors() ) {
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
glPixelStorei(GL_PACK_SKIP_ROWS, 0);
/* BTW: You have to check that your system actually supports the
GL_HALF_FLOAT_NV format extension at all. */
glReadPixels(0, 0, width, width, GL_BGRA, GL_HALF_FLOAT_NV, 0);
if( !check_gl_errors() ) {
Imf::Rgba const * const dest = (Imf::Rgba const*)
glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB);
if( !check_gl_errors() && nullptr != dest ) {
Imf::RgbaOutputFile file_exr(
"/tmp/file.exr",
width, height,
Imf::WRITE_RGBA);
file_exr.setFrameBuffer(dest, 1, width);
file_exr.writePixels(height);
glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
}
else {
/* glMapBuffer failed */
}
}
else {
/* glReadPixels failed */
}
}
else {
/* glBufferDataARB failed => no valid buffer object
to work with in the first place */
}
所有这些错误检查都很重要。它们使您的程序不会崩溃,但会诊断出问题所在。
无论如何,按操作顺序使用 PBO 无论如何都无济于事,因为它在 glReadPixels 操作之后立即被映射,这使得整个事情同步。