0

我正在从帧缓冲区读取单个像素的深度以实现拾取。最初我的 glReadPixels() 需要很长时间(5ms 左右),在 nVidia 上它甚至会在这段时间内消耗 100% 的 CPU 。在 Intel 上它也很慢,但是 CPU 空闲。

从那时起,我使用 PixelBufferObject 功能PBO来使 glReadPixels 异步并且还使用这个众所周知的示例进行双缓冲。

这种方法效果很好,让我异步调用 glReadPixels() ,但前提是我读取 RGBA值。如果我使用相同的 PBO 方法来读取深度值,则 glReadPixels() 会再次阻塞。

读取 RGBA:glReadPixels() 需要 12µs。

读取深度:glReadPixels() 需要 5ms。

我在 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。

4

1 回答 1

1

我实际上直到下一帧才读取像素深度(通过glMapBuffer),因此没有同步进行。glReadPixel 应该触发了异步操作并立即返回(就像 RGBA 一样)。但它没有,对于阅读深度。

那将需要有两个深度缓冲区。但是没有。多缓冲是指颜色缓冲区的数量,因为这些是实际显示的内容。实现几乎从来没有给你多个深度缓冲区。

为了服务从深度缓冲区读取,读取必须在“下一帧”发生之前发生。所以需要同步。

一般来说,最好从您自己的图像中读取。这样,您就可以完全控制格式、重用时间等内容,从而控制同步问题。如果您需要两个深度缓冲区,以便您可以在使用另一个时读取一个,那么您需要创建它。

仅供参考:由于像素所有权问题等,从默认帧缓冲区读取完全是可疑的。但是从前端缓冲区读取几乎总是错误的。

于 2019-05-05T17:38:26.697 回答