user308485
user308485

Reputation: 634

glReadPixels causing crash

I have a 3d scene which I can render on my display. However, in addition to rendering it to display, I would like to also be able to export the rendered scene, say once every 100 frames, as a image (say a JPG or PNG image), maybe saving it as a file somewhere on my machine.

do{
    glfwPollEvents();
    glBindFramebuffer(GL_FRAMEBUFFER, framebuffername);
    drawScene();
    glDrawArrays(GL_TRIANGLES, 0, (GLsizei)vertices.size());
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
    image = (GLuint*)malloc(windowWidth * windowHeight);
    glReadPixels(0, 0, windowWidth, windowHeight, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, &image);
    free(image);
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    drawScene();
    glfwSwapBuffers(window);
} // Check if the ESC key was pressed or the window was closed
while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS &&
       glfwWindowShouldClose(window) == 0 );

What I am trying to do is render my scene both to the display and also to the framebuffer object I have defined. The above crashes and gives me a weird Visual Studio error: "ig75icd64.pdb not loaded". But if I comment out this line:

glReadPixels(0, 0, windowWidth, windowHeight, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, &image);

Then the program does not crash, and it correctly renders to the display (but I want to be able to use glReadPixels to write to a 2d texture). My ultimate goal is to be able to export the display as a formatted image to later do image processing.

Suggestions?

Upvotes: 2

Views: 1448

Answers (1)

Xirema
Xirema

Reputation: 20396

As opined by Derhass, you need to pass the pointer, not the address of the pointer.

This code will (technically) work:

image = (GLuint*)malloc(windowWidth * windowHeight * sizeof(GLuint)); //Need to make it large enough!
glReadPixels(0, 0, windowWidth, windowHeight, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, image); //Note we're not taking the address of image
free(image);

The following code will be much safer, and is all-around better code (assuming you're using C++, which your call to vertices.size() seems to imply):

std::vector<GLuint> image(windowWidth * windowHeight);
glReadPixels(0, 0, windowWidth, windowHeight, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, image.data());

One more consideration: glfwCreateWindow(windowWidth, windowHeight, "Dragon!", nullptr, nullptr); creates a window sized according to the provided width and height, but the actual size of the Framebuffer (the portion of the window where rendering actually takes place) may differ (usually by being smaller), especially if the window is resizable by the user. You should be querying for the size of the Framebuffer before you try to size things:

do {
    glfwPollEvents();
    int fbwidth, fbheight;
    glfwGetFramebufferSize(window, &fbwidth, &fbheight);
    //use fbwidth and fbheight in all code that needs the size of the rendered image
    /*...*/
while(/*...*/);

Upvotes: 5

Related Questions