使用 openGL 的常规 window 屏幕截图

Regular window screen capture using openGL

我正在尝试捕获我的桌面图像。 (所有图像,包括桌面输出到显示器)

使用 window API(BitBlt 或 CImageClass)很容易,但这不是我想要的方式。

我想用 opengl 来做。所以我发现 glReadPixel 函数和 window TRANSPARENT.

但它只是读取像素自己的 Windows 应用程序屏幕。(另存为 bmp 文件并检查)

初始化()

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;

循环

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。是否可以使用 OPENGL 进行桌面捕获(全图像 GPU 输出)?

Q2。如果 Q1 可以,我应该使用 FBO 和 PBO GL_BACK??

Q3。如何访问 mother window 或 GPU 适配器? >> GL似乎强烈反对这一点。(我不想要任何渲染,只是从GPU读取像素数据(桌面图像。不是我的应用程序渲染的。)(如果可能的话......))

有人向我展示 link 或想法吗?

您要求的是完全超出 OpenGL 范围的东西。 OpenGL 被设计为与平台无关 API,应用程序可以以抽象的方式讨论将内容绘制到帧缓冲区中。 OpenGL 没有 windows*、屏幕或桌面的概念。 OpenGL 不在存在此类概念的级别上运行。见鬼,OpenGL 甚至不知道 GPU 是什么。 OpenGL 应该通过特定于平台的机制进行初始化,以建立一个上下文,该上下文为 OpenGL API 调用分配实际含义。据我所知,无法使用帧缓冲区设置 OpenGL 上下文,其内容会以某种方式对应于 Windows(或我知道的任何其他平台)上的桌面。就我的理解而言,这真的没有意义......

要做您想做的事,您必须依赖各自平台特定的 API。 Windows 上最简单的方法可能是为整个桌面获取一个 HDC,并从那里获取 BitBlt。参见,例如,this question for more on that. A more modern approach would be to use the DXGI Desktop Duplication API.

(*) 是的,我知道 OpenGL 规范在技术上确实在一些地方讨论了 "windows";但它只有在谈论所有它不负责的事情时才真正这样做……

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

你不能。 OpenGL 不“了解”桌面或其他 windows(或者实际上根本 windows 是什么)。函数 glReadPixels 仅适用于使用 OpenGL 本身绘制的图像。

您不能使用 OpenGL 截取屏幕截图! 在较旧的计算机上它似乎可以工作,但这只是因为它们较旧的内存管理,当您创建一个新的 window,它的内存将从下面的内容中“截断”,如果您阅读它,它看起来像是一种制作屏幕截图的方法。但事实并非如此。