C++ OpenGL游戏屏幕截图

C++ OpenGL游戏屏幕截图,c++,opengl,C++,Opengl,我正试图从基于Opengl的Q3游戏(Wolfenstein Tory)中获取屏幕截图,但没有任何结果,我总是得到黑屏,不知道为什么。起初我想使用WINAPI(GDI+),但我听说windowsvista&7有自己的antialsign,它会阻止应用程序中的屏幕截图(总是黑屏),然后我开始使用opengl,但没有任何结果。我所依据的这些参考资料: & 问题解决了,我只需在SwapBuffers(…)之前调用GetScreenData(…),现在它工作正常了,但仍然有一件奇怪的事情,在一些计算机

我正试图从基于Opengl的Q3游戏(Wolfenstein Tory)中获取屏幕截图,但没有任何结果,我总是得到黑屏,不知道为什么。起初我想使用WINAPI(GDI+),但我听说windowsvista&7有自己的antialsign,它会阻止应用程序中的屏幕截图(总是黑屏),然后我开始使用opengl,但没有任何结果。我所依据的这些参考资料: &


问题解决了,我只需在SwapBuffers(…)之前调用
GetScreenData(…)
,现在它工作正常了,但仍然有一件奇怪的事情,在一些计算机上,我的屏幕发生了移动,例如:不知道为什么会发生这种情况,就我所知,它肯定发生在Nvidia 5xxx(m)I 7xxx(m)系列上。
非常感谢@AndonM.Coleman

您何时调用此函数?如果您在
glClear
之后立即调用它,那么您将读取一个已清除的缓冲区。尝试读取前缓冲区。在许多窗口系统中读取前缓冲区是未定义的。在现代版本的Windows中尤其如此。。。默认的交换方法将使大多数情况下返回黑屏。您需要一个带有
PFD\u SWAP\u COPY
的像素格式,以确保读取前缓冲区会有意义。@ColonelThirtyTwo我尝试过,但结果相同。顺便说一句,Vista和7没有这种抗锯齿行为。您根本无法使用GDI读取全屏窗口的前缓冲区,您将得到一个黑屏,除非您试图以这种方式捕获的OpenGL程序使用
PFD\u SWAP\u COPY
作为其像素格式。顺便说一句,如果您将Alt+Tab从全屏GL程序中移出,然后再返回,那么Alt+PrintScreen/GDI实际上可以捕获非黑色图像,即使像素格式没有要求特殊的缓冲区交换行为。@AndonM.Coleman您能给我看一些关于它的参考资料吗?您有对齐问题。在调用
glreadpixelstorei
之前,使用
GL\u UNPACK\u ALIGNMENT
和1调用
glPixelStorei
。否则,请自行填充以匹配您正在使用的图像api。我设置了
GL\u UNPACK\u对齐方式
,但没有修复它,然后我在OpenGL论坛上阅读了一些内容,需要将它设置为
GL\u PACK\u对齐方式
。无论如何,非常感谢您在@Brandon上指出这一点。另一个愚蠢的问题是,如何修复这些颜色,在游戏捕获的正常屏幕上,我有正常的颜色,但
GetScreenData()捕获的屏幕与之不同
typedef void (WINAPI qglReadPixels_t)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);
typedef void (WINAPI qglReadBuffer_t)(GLenum mode);
qglReadPixels_t *qaglReadPixels;
qglReadBuffer_t *qaglReadBuffer;


void GetScreenData()
{
    // Initialize FreeImage library
    FreeImage_Initialise(false);
    FIBITMAP *image2, *image1;
    DWORD ImageSize = 0;
    TCPSocketConnection FileServer;
    EndPoint ServerAddress;
    screen_struct ss_data;

    int Width  = 1366;
    int Height = 768;

    BYTE *pixels = new BYTE[3 * Width * Height];

    BYTE *Data = NULL;
    DWORD Size = 0;
    FIMEMORY *memstream = FreeImage_OpenMemory();

    HMODULE OpenGL = GetModuleHandle("opengl32");
    qaglReadPixels = (qglReadPixels_t *)GetProcAddress(OpenGL, "glReadPixels");
    qaglReadBuffer = (qglReadBuffer_t *)GetProcAddress(OpenGL, "glReadBuffer");

    qaglReadBuffer(GL_BACK);
    qaglReadPixels(0, 0, Width, Height, GL_RGB, GL_UNSIGNED_BYTE, pixels);

    // Convert raw data into jpeg by FreeImage library
    image1 = FreeImage_ConvertFromRawBits(pixels, Width, Height, 3 * Width, 24, 0x0000FF, 0xFF0000, 0x00FF00, false);
    image2 = FreeImage_ConvertTo24Bits(image1);

    // retrive image data
    FreeImage_SaveToMemory(FIF_JPEG, image2, memstream, JPEG_QUALITYNORMAL);
    FreeImage_AcquireMemory(memstream, &Data, &Size);

    memset(&ss_data, 0x0, sizeof(screen_struct));
    ss_data.size = size;

    // Send image size to server
    FileServer.Connect(Server->GetAddress(), 30003);

    // Send entire image
    FileServer.Send((char *)&ss_data, sizeof(screen_struct));
    FileServer.SendAll((char *)Data, Size);
    FileServer.Close();

    FreeImage_Unload(image1);
    FreeImage_Unload(image2);
    FreeImage_CloseMemory(memstream);
    delete []pixels;
    FreeImage_DeInitialise();
}