glReadPixels导致崩溃

时间:2017-11-01 17:42:03

标签: c opengl glfw

我有一个可以在显示器上渲染的3D场景。但是,除了渲染它以显示之外,我还希望能够将渲染的场景(例如每100帧一次)导出为图像(比如JPG或PNG图像),也许可以将其保存为我的某处文件。机。

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 );

我要做的是将我的场景渲染到显示器以及我定义的帧缓冲对象。上面的崩溃并给我一个奇怪的Visual Studio错误:“ig75icd64.pdb未加载”。但如果我注释掉这一行:

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

然后程序不会崩溃,并且它正确呈现给显示器(但我希望能够使用glReadPixels写入2d纹理)。我的最终目标是能够将显示器导出为格式化图像,以便以后进行图像处理。

建议?

1 个答案:

答案 0 :(得分:3)

正如Derhass所说,你需要传递指针,而不是指针的地址。

此代码将(技术上)起作用:

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);

以下代码将更加安全,并且是全面更好的代码(假设您正在使用C ++,而您对vertices.size()的调用似乎意味着):

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

还有一个考虑因素:glfwCreateWindow(windowWidth, windowHeight, "Dragon!", nullptr, nullptr);创建一个窗口,根据提供的宽度和高度,但 Framebuffer 的实际大小(实际进行渲染的窗口可能不同(通常通过更小),特别是如果窗口可由用户调整大小。在尝试调整大小之前,您应该查询 Framebuffer 的大小:

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(/*...*/);