c++openglscreen-capturewgl

Regular window screen capture using openGL


I'm trying to my desktop image capture. (All images, including the desktop output to the monitor)

It's easy using window API (BitBlt or CImageClass) and it's not the way I want.

I want do it using opengl. so I found glReadPixel funtion and window TRANSPARENT.

But it just read pixel own Windows application screen.(Save as bmp file and check)

Initialize()

glfwSetErrorCallback(errorCallback);

if (!glfwInit()) {
    std::cerr << "Error: GLFW " << std::endl;
    exit(EXIT_FAILURE);
}
glfwWindowHint(GLFW_DEPTH_BITS, 16);
glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE);

glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_SAMPLES, 4);


const int Monitor_count = GetMonitors();

GLwindow = glfwCreateWindow(
    nWidth, // width
    nHeight, // height
    "OpenGL_Test", // window title
    NULL, NULL);
if (!GLwindow) {
    glfwTerminate();
    exit(EXIT_FAILURE);
}
glfwSwapInterval(1);


if (glfwGetWindowAttrib(GLwindow, GLFW_TRANSPARENT_FRAMEBUFFER))
{
    //...
}
glfwSetWindowOpacity(GLwindow, 0.0f);

auto Mode = glfwGetVideoMode(Monitor[0]);   

glfwMakeContextCurrent(GLwindow);   
glfwSetKeyCallback(GLwindow, keyCallback);

glewExperimental = GL_TRUE;                                         
GLenum errorCode = glewInit();

if (GLEW_OK != errorCode) {

    std::cerr << "Error: GLEW - " << glewGetErrorString(errorCode) << std::endl;
    glfwTerminate();
    exit(EXIT_FAILURE);
}
if (!GLEW_VERSION_3_3) {

    std::cerr << "OpenGL 3.3 API is not available." << std::endl;

    glfwTerminate();
    exit(EXIT_FAILURE);
}

glViewport(0, 0, nWidth, nHeight);

glBindFramebuffer(GL_FRAMEBUFFER, 0);

if (glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) {
    std::cerr << "Error: " << std::endl;
}

return true;

Roop

while (!glfwWindowShouldClose(GLwindow)) {

    Sleep(10);

    glClearColor(0.0f, 0.3f, 0.3f, 0.5f);
    glClear(GL_COLOR_BUFFER_BIT);

    unsigned char *image = (unsigned char*)malloc(sizeof(unsigned char)*nWidth*nHeight * 3);

       glReadPixels(0, 0, nWidth, nHeight, GL_BGR_EXT, GL_UNSIGNED_BYTE, image);
    glfwPollEvents();

}

return true;

Q1. Is it possible desktop capture(Full Image GPU output) with OPENGL?

Q2. If Q1 is possible, Should I use FBO and PBO GL_BACK??

Q3. How to access to mother window or GPU adapter? >> GL seems to strongly reject this.(I don't want any rendering, just read pixel data from GPU(Desktop image. not rendered by my application.)(If it is possible ...))

Anybody shows to me about link or idea?


Solution

  • What you're asking for is something completely outside the scope of OpenGL. OpenGL is designed to be a platform-agnostic API for applications to talk about drawing stuff into framebuffers in an abstract fashion. OpenGL has no notion of windows*, screens, or a desktop. OpenGL doesn't operate at a level where such concepts exist. Heck, OpenGL doesn't even know what a GPU is. OpenGL is supposed to be initialized through platform-specific mechanisms to establish a context which assigns actual meaning to OpenGL API calls. As far as I know, there is no way to set up an OpenGL context with a framebuffer whose contents would somehow correspond to the desktop on Windows (or any other platform I'm aware of). As far as my understanding goes, this wouldn't really make sense…

    To do what you want to do, you'll have to rely on the respective platform-specific APIs. The probably simplest way on Windows is to get an HDC for the entire desktop and BitBlt from there. See, e.g., this question for more on that. A more modern approach would be to use the DXGI Desktop Duplication API.

    (*) yes, I know the OpenGL specification technically does talk about "windows" in a few places; but it only really does so when it's talking about all the things it's not responsible for…