2

OpenGL (VS2012 with freeglut 2.8.1) を使用してウィンドウで実行するプログラムがあります。基本的に、すべての時間ステップ (フックglutPostRedisplayからの呼び出しを介して実行) で、独自の関数を呼び出し、続いて を呼び出して結果を表示します。次に、関数を使用してピクセルを tga ファイルにダンプする独自の関数を呼び出します。glutIdleFuncdrawglFlushscreenShotglReadPixels

このセットアップの問題は、ウィンドウが最小化されたときにファイルが空になることです。つまり、からの出力glReadPixelsは空です。どうすればこれを回避できますか?

これは私が使用している機能のコピーscreenShotです(私は著作権者ではありません):

//////////////////////////////////////////////////
// Grab the OpenGL screen and save it as a .tga //
// Copyright (C) Marius Andra 2001              //
// http://cone3d.gz.ee  EMAIL: cone3d@hot.ee    //
//////////////////////////////////////////////////
// (modified by me a little)
int screenShot(int const num)
{
    typedef unsigned char uchar;
    // we will store the image data here
    uchar *pixels;
    // the thingy we use to write files
    FILE * shot;
    // we get the width/height of the screen into this array
    int screenStats[4];

    // get the width/height of the window
    glGetIntegerv(GL_VIEWPORT, screenStats);

    // generate an array large enough to hold the pixel data 
    // (width*height*bytesPerPixel)
    pixels = new unsigned char[screenStats[2]*screenStats[3]*3];
    // read in the pixel data, TGA's pixels are BGR aligned
    glReadPixels(0, 0, screenStats[2], screenStats[3], 0x80E0, 
    GL_UNSIGNED_BYTE, pixels);

    // open the file for writing. If unsucessful, return 1
    std::string filename = kScreenShotFileNamePrefix + Function::Num2Str(num) + ".tga";

    shot=fopen(filename.c_str(), "wb");

    if (shot == NULL)
        return 1;

    // this is the tga header it must be in the beginning of 
    // every (uncompressed) .tga
    uchar TGAheader[12]={0,0,2,0,0,0,0,0,0,0,0,0};
    // the header that is used to get the dimensions of the .tga
    // header[1]*256+header[0] - width
    // header[3]*256+header[2] - height
    // header[4] - bits per pixel
    // header[5] - ?
    uchar header[6]={((int)(screenStats[2]%256)),
    ((int)(screenStats[2]/256)),
    ((int)(screenStats[3]%256)),
    ((int)(screenStats[3]/256)),24,0};

    // write out the TGA header
    fwrite(TGAheader, sizeof(uchar), 12, shot);
    // write out the header
    fwrite(header, sizeof(uchar), 6, shot);
    // write the pixels
    fwrite(pixels, sizeof(uchar), 
    screenStats[2]*screenStats[3]*3, shot);

    // close the file
    fclose(shot);
    // free the memory
    delete [] pixels;

    // return success
    return 0;
}

では、Windows が実際にコンテンツをモニターに表示するかどうかに関係なく、スクリーンショットを TGA ファイルに出力するにはどうすればよいでしょうか?

注: シミュレーションの進行状況を視覚的に記録しようとしているので、レンダリング中かどうかに関係なく、すべてのフレームを印刷する必要があります。スクリーングラブを生成するにはフレームをレンダリングする必要があるため、最後のステートメントは少し矛盾していることに気付きました。言い換えると; ウィンドウが表示するかどうかに関係なく、ファイルに出力できるように、すべてのステップでプログラムの更新された状態を生成する必要があります(または何らかの代替関数)。glReadPixels

4

2 に答える 2

5

ピクセルの所有権の問題に抵触しているようです。

FBOにレンダリングしglReadPixels()、フロント バッファーの代わりにそこから画像を丸呑みするために使用します。

于 2013-10-04T03:16:43.997 に答える
3

最後にレンダリングされたフレームをメモリに保存しておき、更新が呼び出されて新しいレンダリングに実際のピクセル データがある場合は常に、このメモリの内容を更新することをお勧めします。それか、おそらくaccumを使用できますが、古いフレームをどのように保存するかはよく思い出せません(レンダリングデータも保存しないほど速く更新される可能性があります.

別の解決策は、シェーダーを使用して各フレームを手動でレンダリングし、結果をファイルに書き込むことです。

于 2013-10-04T01:02:01.733 に答える