使用openGL定期窗口截屏

问题描述 投票:0回答:2

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

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

我想用opengl做。所以我发现glReadPixels功能和窗口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。如何访问母窗口或GPU适配器? >> GL似乎强烈反对这一点。(我不想要任何渲染,只需从GPU读取像素数据(桌面图像。不是由我的应用程序渲染。)(如果有可能......))

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

c++ opengl screen-capture wgl
2个回答
1
投票

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

要做你想做的事,你将不得不依赖于各自的平台特定API。 Windows上最简单的方法是从那里获得整个桌面和BitBlt的HDC。有关更多信息,请参阅this question。更现代的方法是使用DXGI Desktop Duplication API

(*)是的,我知道OpenGL规范在技术上确实在几个地方谈论“窗口”;但它只是在谈论它不负责的所有事情时才真正这样做......


1
投票

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

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

但这是它应该完成的方式。

我想用opengl做。所以我发现了glReadPixels的功能

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

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

© www.soinside.com 2019 - 2024. All rights reserved.