首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用DevIL或SOIL保存openGL输出

使用DevIL或SOIL保存openGL输出
EN

Stack Overflow用户
提问于 2013-06-29 01:54:15
回答 3查看 2.2K关注 0票数 2

我已经尝试使用土壤和魔鬼图像库,但创建的屏幕截图是完全黑色的图像。对于魔鬼,我使用了在这里找到的函数Take screenshot with openGL and save it as png,但图像仍然是黑屏。

对于保存屏幕截图或导出opengl输出有什么想法吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-06-29 02:17:45

试试这个:

代码语言:javascript
复制
#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;
}
票数 4
EN

Stack Overflow用户

发布于 2013-06-29 02:14:33

保存来自OpenGL渲染的屏幕截图时最大的问题是,常规系统窗口(通常用作OpenGL的绘图画布)的帧缓冲区是一个极其不可靠的数据来源。如果它被其他窗口(部分)遮挡,某些部分可能根本不包含任何已定义的数据。在缓冲区交换之后,后台缓冲区的内容是未定义的,等等。

以下是一些基本规则:

如果从常规窗口捕获屏幕截图,请从以下任一窗口捕获它们

在绘制完成之后但在缓冲区交换(glReadPixels表示管道中所有绘制操作的刷新和完成,因为它引入了一个同步点)之前立即对后台缓冲区进行交换缓冲区交换之后对前端缓冲区进行

要获得OpenGL渲染的可靠捕获,应渲染到帧缓冲区对象。在那里,图像定义良好,在窗口无效和动画循环或其他奇怪的情况下,不会在一些难以跟踪和调试的竞争条件下“消失”。要显示图片,然后从FBO blit到主帧缓冲区。

票数 1
EN

Stack Overflow用户

发布于 2019-12-30 05:40:36

虽然genpfault的答案做得很好,但它让我找到了一个更清晰的解决方案:

代码语言:javascript
复制
if (!SOIL_save_screenshot("screenshot.bmp",
    SOIL_SAVE_TYPE_BMP, 0, 0, width, height)) {
    // Handle error here
}

这样你就不必设置一个缓冲区,调用glReadPixels,等等。土壤可以自动为你处理所有这些事情!

还要注意,根据genpfault对pslayer89注释的响应,您需要将SOIL_FLAG_INVERT_Y添加到第二个参数中传递的标志(除非您已经使用投影/模型矩阵反转了Y轴)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17370828

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档