Save openGL output using DevIL or SOIL

故事扮演 提交于 2019-12-02 05:52:23

Try this:

#include <vector>
#include <GL/glut.h>
#include <SOIL/SOIL.h>

using namespace std;

bool save = false;
void display()
{
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    glOrtho( -2, 2, -2, 2, -1, 1);

    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();

    glColor3ub( 255, 0, 0 );
    glBegin( GL_QUADS );
    glVertex2i( -1, -1 );
    glVertex2i(  1, -1 );
    glVertex2i(  1,  1 );
    glVertex2i( -1,  1 );
    glEnd();

    if( save )
    {
        int w = glutGet( GLUT_WINDOW_WIDTH );
        int h = glutGet( GLUT_WINDOW_HEIGHT );
        vector< unsigned char > buf( w * h * 3 );

        glPixelStorei( GL_PACK_ALIGNMENT, 1 );
        glReadPixels( 0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, &buf[0] );

        int err = SOIL_save_image
            (
            "img.bmp",
            SOIL_SAVE_TYPE_BMP,
            w, h, 3,
            &buf[0]
            );

        save = false;
    }

    glutSwapBuffers();
}

void keyboard( unsigned char key, int x, int y )
{
    if( key == 's' ) 
    {
        save = true;
        glutPostRedisplay();
    }
}

int main( int argc, char **argv )
{
    glutInit( &argc, argv );
    glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
    glutInitWindowSize( 640, 480 );
    glutCreateWindow( "GLUT" );
    glutDisplayFunc( display );
    glutKeyboardFunc( keyboard );
    glutMainLoop();
    return 0;
}

The biggest problem when saving screenshots from OpenGL renderings is, that the framebuffer of a regular system Window (which you normally use as drawing canvas for OpenGL) is a extremely unreliable source for data. If it's (partially) occluded by other windows some parts may contain no defined data at all. After a buffer swap the contents of the back buffer are undefined, etc. etc.

A few basic rules:

If capturing screenshots from the regular window, capture them from either

  • the back buffer right after the drawing finished but before the buffer swap (glReadPixels implieas a flush and finish of all drawing operations in the pipeline, as it introduces a synchronization point)

  • the front buffer after the buffer swap

To get reliable captures of OpenGL renderings, you should render to a framebuffer object. There the image is well defined and will not "vanish" in some hard to trace and debug race conditions between window invalidations and animation loops or other weird situations. To display the picture you then blit from the FBO to the main framebuffer.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!