我正在使用GLSL在OpenGL(3.X)中实现“深度场”。 它工作得很好,中心深度由着色器(纹理(tex1,vec2(0.5)))占用到自动对焦。但是使用这样的实现焦点会立即发生。他应该喜欢眼睛 - 逐渐适应。为此,我需要CPU内存侧面中间的深度。 我知道如何使用PBO,使用它来读取像素/像素颜色非常快(异步运行),但将GL_RGB更改为GL_DEPTH_COMPONENT性能急剧下降。你知道有什么方法可以比较快地读出中心深度的颜色吗?
glReadPixels(a/2, b/2, 1, 1, GL_RGB , GL_BYTE, 0); // WORKS FINE - 30 ns
glReadPixels(a/2, b/2, 1, 1, GL_DEPTH_COMPONENT, GL_BYTE, 0); // WORKS SLOOOW - around 3500 microseconds
glReadPixels(a/2, b/2, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, 0); // WORKS SLOOOW- around 3500 microseconds
@EDIT: 创建了FBO纹理:
glTexImage2D(GL_TEXTURE_2D, 0,GL_DEPTH_COMPONENT32F , sett.framebuffer_width, sett.framebuffer_height, 0,GL_DEPTH_COMPONENT, GL_FLOAT, 0);
下载深度:
index = (index + 1) % 2;// for ping-pong PBO
nextIndex = (index + 1) % 2;// for ping-pong PBO
glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, pboIds[index]);
glReadPixels(w/2, h/2, 1, 1, GL_DEPTH_COMPONENT , GL_FLOAT, 0);
glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
将深度复制到ram:
GLfloat tabc[10];
glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, pboIds[nextIndex]);
GLfloat* srccccc = (GLfloat*)glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
tabc[0]=*srccccc;
std::cout<<"Depth center: "<<tabc[0]<<std::endl;//only to check is that correct
glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
它现在正在工作,速度更快(从3500微秒开始357微秒)。 现在好吗?所有格式?
答案 0 :(得分:3)
glReadPixels(a/2, b/2, 1, 1, GL_DEPTH_COMPONENT, GL_BYTE, 0); // WORKS SLOOOW - around 3500 ns
glReadPixels(a/2, b/2, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, 0); // WORKS SLOOOW- around 3500 ns
当然他们很慢。一般来说,深度缓冲区既不是8位字节也不是32位浮点值。您回读颜色的原因很快,因为您的pixel transfer format and type符合您的帧缓冲。而且,由于您在回读中非常明智地使用PBO,因此必须对该值进行基于CPU的转换将会影响您的性能。
所以你需要在这里做同样的事情:将像素传输参数与帧缓冲图像匹配。
如果您正在阅读FBO,那么您应该知道图像的确切位深度( 使用sized internal formats,对吧?)。所以简单地匹配:
GL_DEPTH_COMPONENT16 -> GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT
GL_DEPTH_COMPONENT32 -> GL_DEPTH_COMPONENT, GL_UNSIGNED_INT
GL_DEPTH_COMPONENT32F -> GL_DEPTH_COMPONENT, GL_FLOAT
还有一种纯粹的深度缓冲格式:GL_DEPTH_COMPONENT24
。您可以使用GL_UNSIGNED_INT
,但是在编写数据时,OpenGL必须将数据扩展到32位。
这是您应该使用GL_DEPTH24_STENCIL8
的原因之一。对于那个,你可以这样做:
GL_DEPTH24_STENCIL8 -> GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8
您需要将每个32位值右移8位,并在需要深度值时屏蔽前8位。但它应该有用。
如果您正在阅读default framebuffer,那就有点棘手了。在你设置渲染上下文时,你告诉OpenGL你想在帧缓冲中想要什么比特深度的几率很好。但你可能没有得到它们,所以你需要问。
为此,您需要employ glGetFramebufferAttachmentParameter
。有了它,您可以从GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE
附件中查询GL_DEPTH
,从GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE
附件中查询GL_STENCIL
。测试这两个非常重要;如果同时具有深度和模板位,则需要使用深度/模板读取。
一旦你有了bitdepths,只需假装它们是上述内部格式之一并正常进行。