C++ 使用opengl捕获屏幕,始终为黑色

C++ 使用opengl捕获屏幕,始终为黑色,c++,opengl,C++,Opengl,我的项目需要实时捕获屏幕图像部分屏幕,GDI捕获屏幕的方式工作起来很慢,而且占用了太多资源。然后,我想尝试使用opengl glReadpixels读取屏幕并保存到GPU内存PBO。我不能使用窗口捕获,因为应用程序经常更改窗口布局,我需要的是一个固定的矩形区域。 我使用屏幕DC生成opengl上下文,其中包含的setpixel部分生成黑色图像,因为窗口本身只绘制黑色,但在窗口顶部,有其他窗口显示感兴趣的内容 以下是我的部分代码: void CMainWnd::setup_screenca

我的项目需要实时捕获屏幕图像部分屏幕,GDI捕获屏幕的方式工作起来很慢,而且占用了太多资源。然后,我想尝试使用opengl glReadpixels读取屏幕并保存到GPU内存PBO。我不能使用窗口捕获,因为应用程序经常更改窗口布局,我需要的是一个固定的矩形区域。 我使用屏幕DC生成opengl上下文,其中包含的setpixel部分生成黑色图像,因为窗口本身只绘制黑色,但在窗口顶部,有其他窗口显示感兴趣的内容

以下是我的部分代码:

    void CMainWnd::setup_screencapture()
{


    hdcScr=::GetDC(NULL);
        ////searching hints that setpixelformat cannot be done to screen
//but if commented, no context will be able to generate.
        PIXELFORMATDESCRIPTOR pixelDesc =
        {
            sizeof(PIXELFORMATDESCRIPTOR),
            1,
            PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|
            PFD_DOUBLEBUFFER,
            PFD_TYPE_RGBA,
            24,
            0,0,0,0,0,0,
            0,
            0,
            0,
            0,0,0,0,
            32,//
            0,
            0,
            PFD_MAIN_PLANE,
            0,
            0,0,0
        };  

        int n_PixelFormat = ::ChoosePixelFormat(hdcScr,&pixelDesc);
        SetPixelFormat(hdcScr,n_PixelFormat,&pixelDesc);
        ///////////
        hglrcScr = wglCreateContext(hdcScr);

    //clean all buffers
    pbo_indx=0;
    max_num_pbos=100;
    num_frames_captured=0;
    for(int i=0;i<max_num_pbos;i++) pbo_scr_list[i]=0;
    pVideoBuffer=0;

    //the 
    //wglMakeCurrent(hdcScr,hglrcScr);
}

int CMainWnd::capture_screen()
{
    //capture limited rGlWin
    hptime t0;
    double dtime=t0.gettime();
    wglMakeCurrent(hdcScr,hglrcScr);
    screencapture_width=(rGlWin.right-rGlWin.left)/4*4;
    screencapture_height=(rGlWin.bottom-rGlWin.top)/4*4;
    if(!pbo_scr_list[pbo_indx])
    {
        glGenBuffersARB(1,&pbo_scr_list[pbo_indx]);
        glBindBufferARB(GL_PIXEL_PACK_BUFFER,pbo_scr_list[pbo_indx]);
        glBufferDataARB(GL_PIXEL_PACK_BUFFER,screencapture_width*screencapture_height*3,0,GL_DYNAMIC_READ);
        glBindBufferARB(GL_PIXEL_PACK_BUFFER,0);
    }

    glReadBuffer(GL_FRONT); //read the backbuffer
    glBindBufferARB(GL_PIXEL_PACK_BUFFER,pbo_scr_list[pbo_indx]); //link the buffer for pixel reading
    //gl read pixel uses the lower-left corner as 
    glReadPixels(rGlWin.left,rGlWin.bottom,screencapture_width,screencapture_height,GL_BGR,GL_UNSIGNED_BYTE,0);
    glBindBufferARB(GL_PIXEL_PACK_BUFFER,0); //unlink
    pbo_indx++;num_frames_captured++;
    if(pbo_indx>=max_num_pbos) pbo_indx=0;
    if(num_frames_captured>max_num_pbos) num_frames_captured=max_num_pbos;
    wglMakeCurrent(NULL,NULL);
    dtime=t0.gettime()-dtime;
    TRACE("screencapture time=%.2fms\n",dtime);
    return pbo_indx;
}

简化情况:mainwnd是黑色的,包含几个显示图像的子窗口,我想用这些子窗口捕获主窗口的矩形。我使用screen DC生成opengl上下文,但它无法获得正确的屏幕。有人能帮忙吗?非常感谢。

您不能使用OpenGL捕获屏幕。真的吗?你能再给我解释一下吗?或者你有更好的方法吗?就OpenGL而言,任何你没有通过OpenGL渲染创建的帧缓冲区内容都是完全未定义的//阅读backbuffer当然没有任何帮助。您正在读取前端缓冲区,它在Windows Vista或更新版本中非常不可靠。大多数情况下,在从后端到前端交换之后,前端缓冲区的内容会立即被取消定义。在进行缓冲区交换之前,您应该注意读取后缓冲区,因为如果等到交换之后,后缓冲区也可能会变得未定义。但是,当您没有在上下文中绘制任何内容时,这些都不重要。渲染窗口顶部可能有窗口,但它们是完全独立的。窗口管理器会绘制所有这些内容,而您无法访问其他窗口生成的图像。这里的技巧基本上只在GDI处理桌面Windows XP或更早版本时有效-不要在现代版本的Windows中尝试。