Regular window screen capture using openGL

不问归期 提交于 2021-02-08 10:55:38

问题


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?


回答1:


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…




回答2:


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.

But it's the way it's supposed to be done.

I want do it using opengl. so I found glReadPixel funtion

You can't. OpenGL doesn't "know" about the desktop, or other windows (or actually what windows are at all). The function glReadPixels will work reliably only for images that have been drawn with OpenGL itself.

You can't use OpenGL to take screenshots! On older computers it might seem to work, but that's only because of their older memory management where when you create a new window, its memory will be "cut" from what was below and if you read that, it looks like a way to make screenshots. But it is not.



来源:https://stackoverflow.com/questions/55739020/regular-window-screen-capture-using-opengl

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!