Reputation: 313
I am creating a render texture in SFML (sf::RenderTexture
for off-screen rendering), drawing to it and trying to read the pixels asynchronously using PBOs. Here is a minimal example of what I'm doing:
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#define GL_SILENCE_DEPRECATION
#include <SFML/OpenGL.hpp>
#include <iostream>
int main()
{
// create texture and circle to draw on texture
int texSize = 200;
sf::RenderTexture tex;
tex.create(texSize, texSize);
sf::CircleShape circle(50);
circle.setPosition(0, 0);
circle.setFillColor(sf::Color::Blue);
// initialize PBOs
int nPbos = 2;
GLuint* pbos = new GLuint[nPbos];
glGenBuffers(nPbos, pbos);
for (int i = 0; i < nPbos; ++i) {
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbos[i]);
glBufferData(GL_PIXEL_PACK_BUFFER, texSize * texSize * 4, NULL, GL_STREAM_READ);
}
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
int pboIdx = 0;
for (int frame = 0; frame < 100; ++frame) {
// draw stuff
tex.clear(sf::Color::White);
tex.draw(circle);
tex.display();
glReadBuffer(GL_COLOR_ATTACHMENT0);
if (frame < nPbos) {
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbos[pboIdx]);
glReadPixels(0, 0, texSize, texSize, GL_BGRA, GL_UNSIGNED_BYTE, 0);
}
else {
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbos[pboIdx]);
unsigned char* ptr = (unsigned char*)glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
if (ptr != nullptr) {
std::cout << "OK" << std::endl;
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
}
glReadPixels(0, 0, texSize, texSize, GL_BGRA, GL_UNSIGNED_BYTE, 0);
}
pboIdx = (pboIdx + 1) % nPbos;
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
}
return 0;
}
I am not getting error from glGetError()
. However I am never entering the condition, ie. the array of pixels is always empty. I can't figure out what is wrong with the code and why I am not getting the pixels from the texture, am I missing a bind somewhere?
Upvotes: 0
Views: 213
Reputation: 2268
This is a example where data is being read from the color buffer.
This example uses glfw and glew.
#include <gl\glew.h>
#include <glfw3.h>
int w_readIndex = 0;
int w_writeIndex = 1;
int main()
{
// glfw: initialize and configure
// ------------------------------
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// glfw window creation
// --------------------
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
glewInit();
glGenBuffers(2, w_pbo);
glBindBuffer(GL_PIXEL_PACK_BUFFER, w_pbo[0]);
glBufferData(GL_PIXEL_PACK_BUFFER, SCR_WIDTH * SCR_HEIGHT * 4, 0, GL_STREAM_READ);
glBindBuffer(GL_PIXEL_PACK_BUFFER, w_pbo[1]);
glBufferData(GL_PIXEL_PACK_BUFFER, SCR_WIDTH * SCR_HEIGHT * 4, 0, GL_STREAM_READ);
// unbind buffers for now
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
while (!glfwWindowShouldClose(window))
{
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Draw your objects here
w_writeIndex = (w_writeIndex + 1) % 2;
w_readIndex = (w_readIndex + 1) % 2;
glBindBuffer(GL_PIXEL_PACK_BUFFER, w_pbo[w_writeIndex]);
// copy from framebuffer to PBO asynchronously. it will be ready in the NEXT frame
glReadPixels(0, 0, SCR_WIDTH, SCR_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
// now read other PBO which should be already in CPU memory
glBindBuffer(GL_PIXEL_PACK_BUFFER, w_pbo[w_readIndex]);
unsigned char* downsampleData = (unsigned char*)glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
if (downsampleData) {
std::cout << "Pointer is not NULL" << static_cast<unsigned>(downsampleData[2]) << std::endl;
}
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
glfwSwapBuffers(window);
glfwPollEvents();
}
}
Upvotes: 0