我正在从帧缓冲区读取单个像素的深度以实现拾取。最初,我的glReadPixels()花费了很长时间(大约5毫秒),而在nVidia上,它甚至在这段时间内burn 100% CPU。在Intel上,速度也很慢,但是CPU处于空闲状态。
从那时起,我就使用了PixelBufferObject功能 PBO ,使glReadPixels变得异步,并且还使用this well known example进行了双重缓冲。
这种方法效果很好,让我让glReadPixels()调用异步,但前提是我读取RGBA 值。如果我使用相同的PBO方法读取深度值,则glReadPixels()会再次阻塞。
读取RGBA:glReadPixels()需要12µs。
读取深度:glReadPixels()需要5毫秒。
我在nVidia和Intel驱动程序上尝试过此操作。具有不同的格式/类型组合。我尝试过:
glReadPixels( srcx, srcy, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, 0 );
和:
glReadPixels( srcx, srcy, 1, 1, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 0 );
和:
glReadPixels( srcx, srcy, 1, 1, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, 0 );
所有这些都不会导致异步glReadPixels()调用。但是,如果我通过以下调用读取RGBA值:
glReadPixels( srcx, srcy, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 0 );
然后glReadPixels()立即返回,因此不再阻塞。
在读取单个像素之前,我要做:
glReadBuffer( GL_FRONT );
glBindBuffer( GL_PIXEL_PACK_BUFFER, pboid );
然后用以下命令创建双缓冲PBO:
glGenBuffers( NUMPBO, pboids );
for ( int i=0; i<NUMPBO; ++i )
{
const int pboid = pboids[i];
glBindBuffer( GL_PIXEL_PACK_BUFFER, pboid );
glBufferData( GL_PIXEL_PACK_BUFFER, DATA_SIZE, 0, GL_STREAM_READ );
...
我使用深度为24,模板大小为8,默认为双缓冲区的SDL2创建帧缓冲区。
我正在Ubuntu LTS上使用OpenGL Core Profile 3.3。
答案 0 :(得分:1)
我直到下一个帧才真正读取像素深度(通过glMapBuffer),因此没有进行同步。 glReadPixel应该已经触发了异步操作并立即返回(与RGBA一样)。但这不是为了阅读深度。
这将需要两个深度缓冲区。但是没有。多缓冲是指颜色缓冲区的数量,因为这些实际上是显示出来的。实现几乎永远不会给您多个深度缓冲区。
为了服务于深度缓冲区的读取,该读取必须在“下一帧”发生之前进行。因此,需要进行同步。
通常来说,最好阅读自己的图像。这样,您就可以完全控制格式等内容,何时重新使用它们等,从而可以控制同步问题。如果需要两个深度缓冲区,以便在使用另一个深度缓冲区时可以读取其中一个,则需要创建该深度缓冲区。
还有,仅供参考:由于pixel ownership issues等原因,根本无法从默认帧缓冲区中进行读取。但是从 front 缓冲区读取几乎总是错误的事情。