1
General / How to read pixels asynchronously using OpenGL & PBO
« on: January 31, 2022, 07:31:28 pm »
Hello!
I am drawing to a sf::RenderTexture and need to get the drawn image at each frame into an array.
Something like this but faster:
I encountered Pixel Buffer Objects (PBOs) that would allow me to do this by copying from framebuffer to PBO asynchronously and alternating between two PBOs (ie i'd get the pixels with a 1 frame delay). However I'm not familiar with these and my current implementation is not working.
Here is what I am currently doing from what I've found so far:
initialization
then at every frame
Currenty my code never enters the condition, meaning nothing is drawn to the buffer. I tried doing
but I feel like I'm missing something, everything doesn't seem to be bound together correctly. In particular I can't figure out how to make it so that GL_FRONT is linked to the texture I'm drawing to. If I could get help or pointers that would be very appreciated, as I haven't yet found an answer to that online and I'm not sure where to look anymore.
Thanks a lot!
I am drawing to a sf::RenderTexture and need to get the drawn image at each frame into an array.
Something like this but faster:
renderTexture.getTexture().copyToImage().getPixelsPtr();
I encountered Pixel Buffer Objects (PBOs) that would allow me to do this by copying from framebuffer to PBO asynchronously and alternating between two PBOs (ie i'd get the pixels with a 1 frame delay). However I'm not familiar with these and my current implementation is not working.
Here is what I am currently doing from what I've found so far:
initialization
GLuint pbo[2];
int index = 0;
int nextIndex = 1;
int index = 0;
int nextIndex = 1;
then at every frame
// several calls to renderTexture.draw(...);
index = (index + 1) % 2;
nextIndex = (nextIndex + 1) % 2;
glReadBuffer(GL_FRONT); // set target framebuffer to read
// read pixels from framebuffer to PBO asynchronously
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo[index]);
glReadPixels(0, 0, textureWidth, textureHeight, GL_BGRA, GL_UNSIGNED_BYTE, nullptr);
// now read other PBO which should be already in CPU memory
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo[nextIndex]);
unsigned char* ptr = (unsigned char*)glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
if (ptr)
{
pixels_vector.assign(ptr, ptr + textureWidth * textureHeight * 4);
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
}
// back to conventional pixel operation
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
index = (index + 1) % 2;
nextIndex = (nextIndex + 1) % 2;
glReadBuffer(GL_FRONT); // set target framebuffer to read
// read pixels from framebuffer to PBO asynchronously
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo[index]);
glReadPixels(0, 0, textureWidth, textureHeight, GL_BGRA, GL_UNSIGNED_BYTE, nullptr);
// now read other PBO which should be already in CPU memory
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo[nextIndex]);
unsigned char* ptr = (unsigned char*)glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
if (ptr)
{
pixels_vector.assign(ptr, ptr + textureWidth * textureHeight * 4);
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
}
// back to conventional pixel operation
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
Currenty my code never enters the condition, meaning nothing is drawn to the buffer. I tried doing
glBindTexture(GL_TEXTURE_2D, renderTexture.getTexture().getNativeHandle());
but I feel like I'm missing something, everything doesn't seem to be bound together correctly. In particular I can't figure out how to make it so that GL_FRONT is linked to the texture I'm drawing to. If I could get help or pointers that would be very appreciated, as I haven't yet found an answer to that online and I'm not sure where to look anymore.
Thanks a lot!