对于我的算法,我需要能够访问深度缓冲区。我使用 glReadPixels 执行此操作完全没有问题,但读取 800x600 窗口的速度非常慢(从 300 fps 到 20 fps)
我读了很多关于这方面的内容,我认为将深度缓冲区转储到纹理会更快。我知道如何创建纹理,但如何获得深度?
创建 FBO 并从那里创建纹理可能会更快,目前我正在使用 FBO(但仍与 glReadPixels 结合使用)。
那么最快的方法是什么?
(我可能无法使用 GLSL,因为我对它一无所知,而且我没有太多时间来学习,截止日期!)
编辑:
PBO 有效吗?正如这里所描述的:http://www.songho.ca/opengl/gl_pbo.html http://www.songho.ca/opengl/gl_pbo.html它可以快得多,但我不能像示例中那样一直更改缓冲区。
编辑2:
我该如何将深度数据放入 PBO 中?目前我这样做:
glGenBuffersARB(1, &pboId);
glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pboId);
glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, 800*600*sizeof(GLfloat),0, GL_STREAM_READ_ARB);
在我的 readpixels 之前,我再次调用 glBindbuffer 。结果就是我什么也没读。如果我禁用 PBO,一切都会正常。
最终编辑:
我想我已经解决了,我必须使用:
glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pboId);
glReadPixels( 0, 0,Engine::fWidth, Engine::fHeight, GL_DEPTH_COMPONENT,GL_FLOAT, BUFFER_OFFSET(0));
GLuint *pixels = (GLuint*)glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
这使我的 FPS 提高了 20。虽然没那么多,但确实是个东西。
所以,我使用了 2 个 PBO,但我仍然遇到一个问题:我的代码只执行一次。
glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pboIds[index]);
std::cout << "Reading pixels" << std::endl;
glReadPixels( 0, 0,Engine::fWidth, Engine::fHeight, GL_DEPTH_COMPONENT,GL_FLOAT, BUFFER_OFFSET(0));
std::cout << "Getting pixels" << std::endl;
// glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, 800*600*sizeof(GLfloat), 0, GL_STREAM_DRAW_ARB);
GLfloat *pixels = (GLfloat*)glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
int count = 0;
for(int i = 0; i != 800*600; ++i){
std::cout << pixels[i] << std::endl;
}
最后一行执行一次,但仅执行一次,之后它继续调用该方法(这是正常的),但在调用像素时停止。
我显然忘记加载 glUnMapBuffers,这有点解决了它,尽管我的帧速率又变慢了..
我决定尝试一下 FBO,但我偶然发现了一个问题:
初始化 FBO:
glGenFramebuffersEXT(1, framebuffers);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffers[0]);
std::cout << "framebuffer generated, id: " << framebuffers[0] << std::endl;
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
glGenRenderbuffersEXT(1,renderbuffers);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, renderbuffers[0]);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, 800, 600);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, renderbuffers[0]);
bool status = checkFramebufferStatus();
if(!status)
std::cout << "Could not initialise FBO" << std::endl;
else
std::cout << "FBO ready!" << std::endl;
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
我的绘图循环:
GLenum 错误代码;
const GLubyte *errString;
if ((errCode = glGetError()) != GL_NO_ERROR) {
errString = gluErrorString(errCode);
fprintf (stderr, "OpenGL Error: %s\n", errString);
}
++frameCount;
// ----------- First pass to fill the depth buffer -------------------
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffers[0]);
std::cout << "FBO bound" << std::endl;
//Enable depth testing
glEnable(GL_DEPTH_TEST);
glDisable(GL_STENCIL_TEST);
glDepthMask( GL_TRUE );
//Disable stencil test, we don't need that for this pass
glClearStencil(0);
glEnable(GL_STENCIL_TEST);
//Disable drawing to the color buffer
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
//We clear all buffers and reset the modelview matrix
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glLoadIdentity();
//We set our viewpoint
gluLookAt(eyePoint[0],eyePoint[1], eyePoint[2], 0.0,0.0,0.0,0.0,1.0,0.0);
//std::cout << angle << std::endl;
std::cout << "Writing to FBO depth" << std::endl;
//Draw the VBO's, this does not draw anything to the screen, we are just filling the depth buffer
glDrawElements(GL_TRIANGLES, 120, GL_UNSIGNED_SHORT, BUFFER_OFFSET(0));
之后我调用一个调用 glReadPixels() 的函数
该函数甚至没有被调用。循环在函数调用处重新开始。
显然我也解决了这个问题:我必须使用
glReadPixels( 0, 0,Engine::fWidth, Engine::fHeight, GL_DEPTH_COMPONENT,GL_UNSIGNED_SHORT, pixels);
使用 GL_UNSIGNED_SHORT 而不是 GL_FLOAT (或任何其他格式)