【问题标题】:Regular window screen capture using openGL使用 openGL 的常规窗口屏幕截图
【发布时间】:2019-04-18 04:10:59
【问题描述】:

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

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

我想用 opengl 来做。所以我找到了 glReadPixel 函数和窗口 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;

第一季度。是否可以使用 OPENGL 进行桌面捕获(全图像 GPU 输出)?

第二季度。如果 Q1 是可能的,我应该使用 FBO 和 PBO GL_BACK 吗??

第三季度。如何访问母窗口或 GPU 适配器? >> GL 似乎强烈拒绝这一点。(我不想要任何渲染,只需从 GPU 读取像素数据(桌面图像。不是由我的应用程序渲染。)(如果可能的话......))

有人向我展示链接或想法吗?

【问题讨论】:

  • 您发布的代码出了什么问题?
  • 我的代码没有错误,但这不是我想要的。也许观众可以看到和编辑它?
  • @Spektre 谢谢回复。该链接已经存在于我的收藏夹中。但这是从 GPU 中的应用程序获取渲染数据。不是吗?还是我误会了?
  • @Birds 链接的答案中有 2 个部分。第一个只能获取 grom GL 的图像,但第二个获取屏幕上的所有 GDI/GL/DX 内容基本上它会保存您在屏幕上看到的任何内容,除非使用了一些讨厌的技术(覆盖或流式传输)......或“优化”gfx使用了驱动程序......但上次我遇到这样的问题是几年前......

标签: c++ opengl screen-capture wgl


【解决方案1】:

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

要完成您想做的事情,您必须依赖各自平台特定的 API。在 Windows 上可能最简单的方法是从那里为整个桌面和 BitBlt 获取 HDC。有关更多信息,请参见 this question。更现代的方法是使用DXGI Desktop Duplication API

(*) 是的,我知道 OpenGL 规范在技术上确实在一些地方谈到了“窗口”;但它只有在谈论它不负责的所有事情时才会这样做……

【讨论】:

  • 非常感谢您的回答。 “只有当它谈论所有它不负责的事情时才真正这样做……”负责任的意思是什么?
  • @Birds “窗口”一词确实出现在 OpenGL 规范中。但它只在规范讨论所有 OpenGL 不关心的东西的地方才真正这样做,并且以特定坐标系的名义。您可以简单地忽略这一点,这是一个次要的技术性问题,并不是很重要。我只是补充说在技术上是正确的......;)关键是 OpenGL 的抽象存在于一个远远超出你在这里尝试做的事情的水平......
  • 这对我很有帮助。谢谢。总之,这是否意味着你不能用 OPENGL 做到这一点?还是使用 WINAPI?
  • 据我所知,你不能用 OpenGL 做你想做的事情。您可以使用 Windows API 做到这一点。
【解决方案2】:

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

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

但这是应​​该的方式。

我想用 opengl 来做。所以我找到了 glReadPixel 函数

你不能。 OpenGL 不“知道”桌面或其他窗口(或实际上是什么窗口)。 glReadPixels 函数仅对使用 OpenGL 本身绘制的图像可靠地工作。

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

【讨论】:

    猜你喜欢
    • 2012-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多